You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ma...@apache.org on 2015/07/20 19:14:31 UTC
[01/50] [abbrv] phoenix git commit: PHOENIX-2036 -
PhoenixConfigurationUtil should provide a pre-normalize table name to
PhoenixRuntime
Repository: phoenix
Updated Branches:
refs/heads/calcite 0641043a4 -> 76e92a961
PHOENIX-2036 - PhoenixConfigurationUtil should provide a pre-normalize table name to PhoenixRuntime
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/be5aba5b
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/be5aba5b
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/be5aba5b
Branch: refs/heads/calcite
Commit: be5aba5bcdbbf28c4faa04414e9e4f4079276614
Parents: 1c10fda
Author: ravimagham <ra...@apache.org>
Authored: Sat Jul 4 08:11:25 2015 -0700
Committer: ravimagham <ra...@apache.org>
Committed: Sat Jul 4 08:11:25 2015 -0700
----------------------------------------------------------------------
.../org/apache/phoenix/util/PhoenixRuntime.java | 3 +-
.../java/org/apache/phoenix/util/QueryUtil.java | 4 +-
.../org/apache/phoenix/util/SchemaUtil.java | 18 ++++++-
.../phoenix/pig/PhoenixHBaseLoaderIT.java | 9 ++--
.../phoenix/pig/PhoenixHBaseStorerIT.java | 4 +-
.../apache/phoenix/pig/PhoenixHBaseStorage.java | 51 ++++++++------------
6 files changed, 47 insertions(+), 42 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/be5aba5b/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 4347acd..92bb1d8 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
@@ -354,8 +354,7 @@ public class PhoenixRuntime {
public static List<ColumnInfo> generateColumnInfo(Connection conn,
String tableName, List<String> columns)
throws SQLException {
-
- PTable table = PhoenixRuntime.getTable(conn, tableName);
+ PTable table = PhoenixRuntime.getTable(conn, SchemaUtil.normalizeFullTableName(tableName));
List<ColumnInfo> columnInfoList = Lists.newArrayList();
Set<String> unresolvedColumnNames = new TreeSet<String>();
if (columns == null) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/be5aba5b/phoenix-core/src/main/java/org/apache/phoenix/util/QueryUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/QueryUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/QueryUtil.java
index bc2141c..d7f9cea 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/QueryUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/QueryUtil.java
@@ -201,8 +201,6 @@ public final class QueryUtil {
if(columnInfos == null || columnInfos.isEmpty()) {
throw new IllegalArgumentException("At least one column must be provided");
}
- // escape the table name to ensure it is case sensitive.
- final String escapedFullTableName = SchemaUtil.getEscapedFullTableName(fullTableName);
StringBuilder query = new StringBuilder();
query.append("SELECT ");
for (ColumnInfo cinfo : columnInfos) {
@@ -215,7 +213,7 @@ public final class QueryUtil {
// Remove the trailing comma
query.setLength(query.length() - 1);
query.append(" FROM ");
- query.append(escapedFullTableName);
+ query.append(fullTableName);
if(conditions != null && conditions.length() > 0) {
query.append(" WHERE (").append(conditions).append(")");
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/be5aba5b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
index aff6b51..c674140 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
@@ -21,9 +21,8 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_STATS_NAME_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_FUNCTION_NAME_BYTES;
-
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_STATS_NAME_BYTES;
import java.sql.SQLException;
import java.sql.Statement;
@@ -174,6 +173,21 @@ public class SchemaUtil {
}
return name.toUpperCase();
}
+
+ /**
+ * Normalizes the fulltableName . Uses {@linkplain normalizeIdentifier}
+ * @param fullTableName
+ * @return
+ */
+ public static String normalizeFullTableName(String fullTableName) {
+ String schemaName = SchemaUtil.getSchemaNameFromFullName(fullTableName);
+ String tableName = SchemaUtil.getTableNameFromFullName(fullTableName);
+ String normalizedTableName = StringUtil.EMPTY_STRING;
+ if(!schemaName.isEmpty()) {
+ normalizedTableName = normalizeIdentifier(schemaName) + QueryConstants.NAME_SEPARATOR;
+ }
+ return normalizedTableName + normalizeIdentifier(tableName);
+ }
public static boolean isCaseSensitive(String name) {
return name!=null && name.length() > 0 && name.charAt(0)=='"';
http://git-wip-us.apache.org/repos/asf/phoenix/blob/be5aba5b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
index 594abe6..7fcf6ac 100644
--- a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
+++ b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
@@ -74,6 +74,8 @@ public class PhoenixHBaseLoaderIT {
private static final String TABLE_NAME = "A";
private static final String INDEX_NAME = "I";
private static final String TABLE_FULL_NAME = SchemaUtil.getTableName(SCHEMA_NAME, TABLE_NAME);
+ private static final String CASE_SENSITIVE_TABLE_NAME = SchemaUtil.getEscapedArgument("a");
+ private static final String CASE_SENSITIVE_TABLE_FULL_NAME = SchemaUtil.getTableName(SCHEMA_NAME,CASE_SENSITIVE_TABLE_NAME);
private static HBaseTestingUtility hbaseTestUtil;
private static String zkQuorum;
private static Connection conn;
@@ -234,13 +236,13 @@ public class PhoenixHBaseLoaderIT {
public void testDataForTable() throws Exception {
//create the table
- String ddl = "CREATE TABLE " + TABLE_FULL_NAME
+ String ddl = "CREATE TABLE " + CASE_SENSITIVE_TABLE_FULL_NAME
+ " (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR, AGE INTEGER) ";
conn.createStatement().execute(ddl);
//prepare data with 10 rows having age 25 and the other 30.
- final String dml = "UPSERT INTO " + TABLE_FULL_NAME + " VALUES(?,?,?)";
+ final String dml = "UPSERT INTO " + CASE_SENSITIVE_TABLE_FULL_NAME + " VALUES(?,?,?)";
PreparedStatement stmt = conn.prepareStatement(dml);
int rows = 20;
for(int i = 0 ; i < rows; i++) {
@@ -253,7 +255,7 @@ public class PhoenixHBaseLoaderIT {
//load data and filter rows whose age is > 25
pigServer.registerQuery(String.format(
- "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", TABLE_FULL_NAME,
+ "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", CASE_SENSITIVE_TABLE_FULL_NAME,
zkQuorum));
pigServer.registerQuery("B = FILTER A BY AGE > 25;");
@@ -603,6 +605,7 @@ public class PhoenixHBaseLoaderIT {
@After
public void tearDown() throws Exception {
dropTable(TABLE_FULL_NAME);
+ dropTable(CASE_SENSITIVE_TABLE_FULL_NAME);
pigServer.shutdown();
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/be5aba5b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseStorerIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseStorerIT.java b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseStorerIT.java
index 67abf62..9106cdd 100644
--- a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseStorerIT.java
+++ b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseStorerIT.java
@@ -33,6 +33,7 @@ import java.util.Collection;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.end2end.BaseHBaseManagedTimeIT;
+import org.apache.phoenix.util.SchemaUtil;
import org.apache.pig.ExecType;
import org.apache.pig.PigServer;
import org.apache.pig.backend.executionengine.ExecJob.JOB_STATUS;
@@ -140,12 +141,11 @@ public class PhoenixHBaseStorerIT extends BaseHBaseManagedTimeIT {
*/
@Test
public void testStorerForSpecificColumns() throws Exception {
- final String tableName = "TABLE2";
+ final String tableName = SchemaUtil.getTableName("TABLE2", SchemaUtil.getEscapedArgument("zo2"));
final Statement stmt = conn.createStatement();
stmt.execute("CREATE TABLE " + tableName +
" (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR, AGE INTEGER)");
-
final Data data = Storage.resetData(pigServer);
final Collection<Tuple> list = Lists.newArrayList();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/be5aba5b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java
index 72d958b..4ada303 100644
--- a/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java
+++ b/phoenix-pig/src/main/java/org/apache/phoenix/pig/PhoenixHBaseStorage.java
@@ -18,8 +18,6 @@
package org.apache.phoenix.pig;
import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
@@ -33,12 +31,14 @@ import org.apache.commons.cli.ParseException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.OutputFormat;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.phoenix.mapreduce.PhoenixOutputFormat;
import org.apache.phoenix.mapreduce.util.PhoenixConfigurationUtil;
+import org.apache.phoenix.pig.util.TableSchemaParserFunction;
import org.apache.phoenix.pig.writable.PhoenixPigDBWritable;
import org.apache.phoenix.util.ColumnInfo;
import org.apache.pig.ResourceSchema;
@@ -88,12 +88,12 @@ public class PhoenixHBaseStorage implements StoreFuncInterface {
private ResourceSchema schema;
private long batchSize;
private final PhoenixOutputFormat outputFormat = new PhoenixOutputFormat();
-
// Set of options permitted
private final static Options validOptions = new Options();
private final static CommandLineParser parser = new GnuParser();
private final static String SCHEMA = "_schema";
-
+ private final static String PHOENIX_TABLE_NAME_SCHEME = "hbase://";
+
private final CommandLine configuredOptions;
private final String server;
@@ -134,33 +134,24 @@ public class PhoenixHBaseStorage implements StoreFuncInterface {
*/
@Override
public void setStoreLocation(String location, Job job) throws IOException {
- URI locationURI;
- try {
- locationURI = new URI(location);
- if (!"hbase".equals(locationURI.getScheme())) {
- throw new IOException(String.format("Location must use the hbase protocol, hbase://tableName[/columnList]. Supplied location=%s",location));
- }
-
- PhoenixConfigurationUtil.loadHBaseConfiguration(job);
- config = job.getConfiguration();
- config.set(HConstants.ZOOKEEPER_QUORUM, server);
- String tableName = locationURI.getAuthority();
- // strip off the leading path token '/'
- String columns = null;
- if(!locationURI.getPath().isEmpty()) {
- columns = locationURI.getPath().substring(1);
- PhoenixConfigurationUtil.setUpsertColumnNames(config, columns);
- }
- PhoenixConfigurationUtil.setOutputTableName(config,tableName);
- PhoenixConfigurationUtil.setBatchSize(config,batchSize);
- String serializedSchema = getUDFProperties().getProperty(contextSignature + SCHEMA);
- if (serializedSchema != null) {
- schema = (ResourceSchema) ObjectSerializer.deserialize(serializedSchema);
- }
- } catch (URISyntaxException e) {
- throw new IOException(String.format("Location must use the hbase protocol, hbase://tableName[/columnList]. Supplied location=%s",location),e);
+ String tableSchema = location.substring(PHOENIX_TABLE_NAME_SCHEME.length());
+ final TableSchemaParserFunction parseFunction = new TableSchemaParserFunction();
+ Pair<String,String> pair = parseFunction.apply(tableSchema);
+ PhoenixConfigurationUtil.loadHBaseConfiguration(job);
+ config = job.getConfiguration();
+ config.set(HConstants.ZOOKEEPER_QUORUM, server);
+ String tableName = pair.getFirst();
+ String columns = pair.getSecond();
+ if(columns != null && columns.length() > 0) {
+ PhoenixConfigurationUtil.setUpsertColumnNames(config, columns);
}
- }
+ PhoenixConfigurationUtil.setOutputTableName(config,tableName);
+ PhoenixConfigurationUtil.setBatchSize(config,batchSize);
+ String serializedSchema = getUDFProperties().getProperty(contextSignature + SCHEMA);
+ if (serializedSchema != null) {
+ schema = (ResourceSchema) ObjectSerializer.deserialize(serializedSchema);
+ }
+ }
@SuppressWarnings("unchecked")
@Override
[50/50] [abbrv] phoenix git commit: Fix compilation errors after merge
Posted by ma...@apache.org.
Fix compilation errors after merge
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/76e92a96
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/76e92a96
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/76e92a96
Branch: refs/heads/calcite
Commit: 76e92a96127fb9c828dab95dc7e6e66e0e4adc12
Parents: 597e001
Author: maryannxue <we...@intel.com>
Authored: Mon Jul 20 13:14:07 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Mon Jul 20 13:14:07 2015 -0400
----------------------------------------------------------------------
.../it/java/org/apache/phoenix/calcite/CalciteTest.java | 12 ++++++------
.../phoenix/calcite/rel/PhoenixRelImplementorImpl.java | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76e92a96/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
index 1452ac9..08d272f 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
@@ -34,7 +34,7 @@ public class CalciteTest extends BaseClientManagedTimeIT {
public static final String ATABLE_NAME = "ATABLE";
public static Start start() {
- return new Start(new Properties(), false);
+ return new Start(getConnectionProps(false), false);
}
public static Start start(Properties props, boolean connectUsingModel) {
@@ -238,11 +238,11 @@ public class CalciteTest extends BaseClientManagedTimeIT {
return connection;
}
- private static Properties getMaterializationEnabledProps() {
+ private static Properties getConnectionProps(boolean enableMaterialization) {
Properties props = new Properties();
props.setProperty(
CalciteConnectionProperty.MATERIALIZATIONS_ENABLED.camelName(),
- Boolean.toString(true));
+ Boolean.toString(enableMaterialization));
props.setProperty(
CalciteConnectionProperty.CREATE_MATERIALIZATIONS.camelName(),
Boolean.toString(false));
@@ -859,7 +859,7 @@ public class CalciteTest extends BaseClientManagedTimeIT {
} catch (Exception e) {
throw new RuntimeException(e);
}
- final Start start = start(getMaterializationEnabledProps(), false);
+ final Start start = start(getConnectionProps(true), false);
start.sql("select x_integer from aTable")
.explainIs("PhoenixToEnumerableConverter\n" +
" PhoenixToClientConverter\n" +
@@ -888,7 +888,7 @@ public class CalciteTest extends BaseClientManagedTimeIT {
start.sql("select a_string, b_string from aTable where a_string = 'a'")
.explainIs("PhoenixToEnumerableConverter\n" +
" PhoenixToClientConverter\n" +
- " PhoenixServerProject(0:A_STRING=[$0], 0:B_STRING=[$3])\n" +
+ " PhoenixServerProject(A_STRING=[$0], B_STRING=[$3])\n" +
" PhoenixTableScan(table=[[phoenix, IDX1]], filter=[=($0, 'a')])\n")
.close();
start.sql("select a_string, b_string from aTable where b_string = 'b'")
@@ -902,7 +902,7 @@ public class CalciteTest extends BaseClientManagedTimeIT {
" PhoenixToClientConverter\n" +
" PhoenixServerProject(A_STRING=[$3], B_STRING=[$0], X_INTEGER=[$10], Y_INTEGER=[$11])\n" +
" PhoenixTableScan(table=[[phoenix, IDX_FULL]], filter=[=($0, 'b')])\n")
- .close();
+ .close();
}
@Test public void testConnectJoinHsqldb() {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/76e92a96/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRelImplementorImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRelImplementorImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRelImplementorImpl.java
index 2ae3838..28b4f51 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRelImplementorImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRelImplementorImpl.java
@@ -119,7 +119,7 @@ public class PhoenixRelImplementorImpl implements PhoenixRel.Implementor {
PTableType.SUBQUERY, null, MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM,
null, null, columns, null, null, Collections.<PTable>emptyList(),
false, Collections.<PName>emptyList(), null, null, false, false, false, null,
- null, null);
+ null, null, true);
this.setTableRef(new TableRef(CalciteUtils.createTempAlias(), pTable, HConstants.LATEST_TIMESTAMP, false));
} catch (SQLException e) {
throw new RuntimeException(e);
[48/50] [abbrv] phoenix git commit: PHOENIX-2131 Closing paren in
CastParseNode SQL
Posted by ma...@apache.org.
PHOENIX-2131 Closing paren in CastParseNode SQL
Add a missing closing parenthesis in CastParseNode.toSQL.
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/b38a6243
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/b38a6243
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/b38a6243
Branch: refs/heads/calcite
Commit: b38a62431ee44df171c913097d18e2433c951466
Parents: b329e85
Author: Gabriel Reid <gr...@apache.org>
Authored: Sun Jul 19 17:46:48 2015 +0200
Committer: Gabriel Reid <ga...@ngdata.com>
Committed: Mon Jul 20 15:25:01 2015 +0200
----------------------------------------------------------------------
.../org/apache/phoenix/parse/CastParseNode.java | 2 +-
.../apache/phoenix/parse/CastParseNodeTest.java | 57 ++++++++++++++++++++
2 files changed, 58 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b38a6243/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java
index 78be616..3e03613 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/CastParseNode.java
@@ -133,7 +133,7 @@ public class CastParseNode extends UnaryParseNode {
if (isArray) {
buf.append(' ');
buf.append(PDataType.ARRAY_TYPE_SUFFIX);
- buf.append(' ');
}
+ buf.append(")");
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b38a6243/phoenix-core/src/test/java/org/apache/phoenix/parse/CastParseNodeTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/parse/CastParseNodeTest.java b/phoenix-core/src/test/java/org/apache/phoenix/parse/CastParseNodeTest.java
new file mode 100644
index 0000000..b62d9a9
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/parse/CastParseNodeTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.parse;
+
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.schema.types.PLong;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class CastParseNodeTest {
+
+ @Test
+ public void testToSQL() {
+ ColumnParseNode columnParseNode = new ColumnParseNode(TableName.create("SCHEMA1", "TABLE1"), "V");
+ CastParseNode castParseNode = new CastParseNode(columnParseNode, PLong.INSTANCE, null, null, false);
+ StringBuilder stringBuilder = new StringBuilder();
+ castParseNode.toSQL(null, stringBuilder);
+ assertEquals(" CAST(TABLE1.V AS BIGINT)", stringBuilder.toString());
+ }
+
+ @Test
+ public void testToSQL_WithLengthAndScale() {
+ ColumnParseNode columnParseNode = new ColumnParseNode(TableName.create("SCHEMA1", "TABLE1"), "V");
+ CastParseNode castParseNode = new CastParseNode(columnParseNode, PDecimal.INSTANCE, 5, 3, false);
+ StringBuilder stringBuilder = new StringBuilder();
+ castParseNode.toSQL(null, stringBuilder);
+ assertEquals(" CAST(TABLE1.V AS DECIMAL(5,3))", stringBuilder.toString());
+ }
+
+ @Test
+ public void testToSQL_ArrayType() {
+ ColumnParseNode columnParseNode = new ColumnParseNode(TableName.create("SCHEMA1", "TABLE1"), "V");
+ CastParseNode castParseNode = new CastParseNode(columnParseNode, PLong.INSTANCE, null, null, true);
+ StringBuilder stringBuilder = new StringBuilder();
+ castParseNode.toSQL(null, stringBuilder);
+ assertEquals(" CAST(TABLE1.V AS BIGINT ARRAY)", stringBuilder.toString());
+ }
+}
\ No newline at end of file
[28/50] [abbrv] phoenix git commit: PHOENIX-2058 Check for existence
and compatibility of columns being added in view
Posted by ma...@apache.org.
PHOENIX-2058 Check for existence and compatibility of columns being added in view
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/01b4f605
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/01b4f605
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/01b4f605
Branch: refs/heads/calcite
Commit: 01b4f6055911aa5036aa1e3a79340f80eb08396a
Parents: 66705d5
Author: Thomas D'Silva <td...@salesforce.com>
Authored: Fri Jul 10 11:55:55 2015 -0700
Committer: Thomas D'Silva <td...@salesforce.com>
Committed: Mon Jul 13 17:37:58 2015 -0700
----------------------------------------------------------------------
.../apache/phoenix/end2end/AlterTableIT.java | 311 ++++++++++++++++---
.../java/org/apache/phoenix/end2end/ViewIT.java | 6 +
.../coprocessor/MetaDataEndpointImpl.java | 64 ++--
.../apache/phoenix/schema/MetaDataClient.java | 9 +-
4 files changed, 310 insertions(+), 80 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/01b4f605/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 0425933..607f52a 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
@@ -2009,7 +2009,7 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
@Test
- public void testAddNewColumnToBaseTableWithViews() throws Exception {
+ public void testAddNewColumnsToBaseTableWithViews() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
try {
conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
@@ -2018,13 +2018,15 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
+ " COL2 bigint NOT NULL,"
+ " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+ " )");
- assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR ) AS SELECT * FROM TABLEWITHVIEW");
assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
- conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD COL3 char(10)");
- assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 6, 4, "ID", "COL1", "COL2", "COL3", "VIEW_COL1", "VIEW_COL2");
+ // adding a new pk column and a new regular column
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD COL3 varchar(10) PRIMARY KEY, COL4 integer");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "COL3", "COL4");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 7, 5, "ID", "COL1", "COL2", "COL3", "COL4", "VIEW_COL1", "VIEW_COL2");
} finally {
conn.close();
}
@@ -2040,13 +2042,13 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
+ " COL2 bigint NOT NULL,"
+ " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+ " )");
- assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
- conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256), VIEW_COL3 VARCHAR, VIEW_COL4 DECIMAL ) AS SELECT * FROM TABLEWITHVIEW");
- assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 7, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4");
+ conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256), VIEW_COL3 VARCHAR, VIEW_COL4 DECIMAL, VIEW_COL5 DECIMAL(10,2), VIEW_COL6 VARCHAR, CONSTRAINT pk PRIMARY KEY (VIEW_COL5, VIEW_COL6) ) AS SELECT * FROM TABLEWITHVIEW");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 9, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4", "VIEW_COL5", "VIEW_COL6");
// upsert single row into view
- String dml = "UPSERT INTO VIEWOFTABLE VALUES(?,?,?,?,?, ?, ?)";
+ String dml = "UPSERT INTO VIEWOFTABLE VALUES(?,?,?,?,?, ?, ?, ?, ?)";
PreparedStatement stmt = conn.prepareStatement(dml);
stmt.setString(1, "view1");
stmt.setInt(2, 12);
@@ -2055,6 +2057,8 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
stmt.setString(5, "view5");
stmt.setString(6, "view6");
stmt.setInt(7, 17);
+ stmt.setInt(8, 18);
+ stmt.setString(9, "view9");
stmt.execute();
conn.commit();
@@ -2068,7 +2072,7 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
try {
- // should fail because there is already a view column with same name with a higher scale
+ // should fail because there is already a view column with same name with different scale
conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,1)");
fail();
}
@@ -2077,8 +2081,8 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
try {
- // should fail because there is already a view column with same name with a greater length
- conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 VARCHAR(256)");
+ // should fail because there is already a view column with same name with different length
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(9,2)");
fail();
}
catch (SQLException e) {
@@ -2086,8 +2090,8 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
try {
- // should fail because there is already a view column with null length
- conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 DECIMAL(9,2)");
+ // should fail because there is already a view column with different length
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR");
fail();
}
catch (SQLException e) {
@@ -2095,35 +2099,36 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
// validate that there were no columns added to the table or view
- assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
- assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 7, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 9, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4", "VIEW_COL5", "VIEW_COL6");
- // should succeed because even though there already is a view column with same name,
- // the column being added has a scale and max length that is equal to or greater
- conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR, VIEW_COL4 DECIMAL");
- assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 4, -1, "ID", "COL1", "COL2", "VIEW_COL2", "VIEW_COL4");
- assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 7, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4");
+ // should succeed
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL4 DECIMAL, VIEW_COL2 VARCHAR(256)");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL4", "VIEW_COL2");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 9, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4", "VIEW_COL5", "VIEW_COL6");
// query table
ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
assertTrue(rs.next());
- assertEquals(rs.getString(1), "view1");
- assertEquals(rs.getInt(2), 12);
- assertEquals(rs.getInt(3), 13);
- assertEquals(rs.getString(4), "view5");
- assertEquals(rs.getInt(5), 17);
+ assertEquals("view1", rs.getString("ID"));
+ assertEquals(12, rs.getInt("COL1"));
+ assertEquals(13, rs.getInt("COL2"));
+ assertEquals("view5", rs.getString("VIEW_COL2"));
+ assertEquals(17, rs.getInt("VIEW_COL4"));
assertFalse(rs.next());
// query view
rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE");
assertTrue(rs.next());
- assertEquals(rs.getString(1), "view1");
- assertEquals(rs.getInt(2), 12);
- assertEquals(rs.getInt(3), 13);
- assertEquals(rs.getInt(4), 14);
- assertEquals(rs.getString(5),"view5");
- assertEquals(rs.getString(6),"view6");
- assertEquals(rs.getInt(7), 17);
+ assertEquals("view1", rs.getString("ID"));
+ assertEquals(12, rs.getInt("COL1"));
+ assertEquals(13, rs.getInt("COL2"));
+ assertEquals(14, rs.getInt("VIEW_COL1"));
+ assertEquals("view5", rs.getString("VIEW_COL2"));
+ assertEquals("view6", rs.getString("VIEW_COL3"));
+ assertEquals(17, rs.getInt("VIEW_COL4"));
+ assertEquals(18, rs.getInt("VIEW_COL5"));
+ assertEquals("view9", rs.getString("VIEW_COL6"));
assertFalse(rs.next());
} finally {
conn.close();
@@ -2140,7 +2145,7 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
+ " COL2 integer NOT NULL,"
+ " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+ " )");
- assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
@@ -2157,8 +2162,53 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
conn.commit();
try {
- // should fail because there is already a pk view column with same name is a different slot
- conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR PRIMARY KEY");
+ // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256)");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 to the pk in the right order
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY, VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there we have to add both VIEW_COL1 and VIEW_COL2 with the right sort order
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY DESC, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
fail();
}
catch (SQLException e) {
@@ -2166,33 +2216,194 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
// add the pk column of the view to the base table
- conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
- assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 4, -1, "ID", "COL1", "COL2", "VIEW_COL1");
- assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 4, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
// query table
ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
assertTrue(rs.next());
- assertEquals(rs.getString(1), "view1");
- assertEquals(rs.getInt(2), 12);
- assertEquals(rs.getInt(3), 13);
- assertEquals(rs.getBigDecimal(4).intValue(), 14);
+ assertEquals("view1", rs.getString("ID"));
+ assertEquals(12, rs.getInt("COL1"));
+ assertEquals(13, rs.getInt("COL2"));
+ assertEquals(14, rs.getInt("VIEW_COL1"));
+ assertEquals("view5", rs.getString("VIEW_COL2"));
assertFalse(rs.next());
// query view
rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE");
assertTrue(rs.next());
- assertEquals(rs.getString(1), "view1");
- assertEquals(rs.getInt(2), 12);
- assertEquals(rs.getInt(3), 13);
- assertEquals(rs.getInt(4), 14);
- assertEquals(rs.getString(5),"view5");
+ assertEquals("view1", rs.getString("ID"));
+ assertEquals(12, rs.getInt("COL1"));
+ assertEquals(13, rs.getInt("COL2"));
+ assertEquals(14, rs.getInt("VIEW_COL1"));
+ assertEquals("view5", rs.getString("VIEW_COL2"));
assertFalse(rs.next());
} finally {
conn.close();
}
}
+
+ @Test
+ public void testAddExistingViewPkColumnToBaseTableWithMultipleViews() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+ + " ID char(10) NOT NULL,"
+ + " COL1 integer NOT NULL,"
+ + " COL2 integer NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+ + " )");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+
+ conn.createStatement().execute("CREATE VIEW VIEWOFTABLE1 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
+ assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+
+ conn.createStatement().execute("CREATE VIEW VIEWOFTABLE2 ( VIEW_COL3 VARCHAR(256), VIEW_COL4 DECIMAL(10,2) CONSTRAINT pk PRIMARY KEY (VIEW_COL3, VIEW_COL4)) AS SELECT * FROM TABLEWITHVIEW");
+ assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL3", "VIEW_COL4");
+
+ try {
+ // should fail because there are two view with different pk columns
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there are two view with different pk columns
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because slot positions of pks are different
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY, VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because slot positions of pks are different
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL3 VARCHAR PRIMARY KEY, VIEW_COL4 DECIMAL PRIMARY KEY, VIEW_COL1 DECIMAL PRIMARY KEY, VIEW_COL2 VARCHAR PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testAddExistingViewPkColumnToBaseTableWithMultipleViewsHavingSamePks() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+ + " ID char(10) NOT NULL,"
+ + " COL1 integer NOT NULL,"
+ + " COL2 integer NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+ + " )");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2");
+
+ conn.createStatement().execute("CREATE VIEW VIEWOFTABLE1 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
+ assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+
+ conn.createStatement().execute("CREATE VIEW VIEWOFTABLE2 ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
+ assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+
+ // upsert single row into both view
+ String dml = "UPSERT INTO VIEWOFTABLE1 VALUES(?,?,?,?,?)";
+ PreparedStatement stmt = conn.prepareStatement(dml);
+ stmt.setString(1, "view1");
+ stmt.setInt(2, 12);
+ stmt.setInt(3, 13);
+ stmt.setInt(4, 14);
+ stmt.setString(5, "view5");
+ stmt.execute();
+ conn.commit();
+ dml = "UPSERT INTO VIEWOFTABLE2 VALUES(?,?,?,?,?)";
+ stmt = conn.prepareStatement(dml);
+ stmt.setString(1, "view1");
+ stmt.setInt(2, 12);
+ stmt.setInt(3, 13);
+ stmt.setInt(4, 14);
+ stmt.setString(5, "view5");
+ stmt.execute();
+ conn.commit();
+
+ try {
+ // should fail because the view have two extra columns in their pk
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because the view have two extra columns in their pk
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because slot positions of pks are different
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 DECIMAL(10,2) PRIMARY KEY, VIEW_COL1 VARCHAR(256) PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY, VIEW_COL2 VARCHAR(256) PRIMARY KEY");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 5, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+ assertTableDefinition(conn, "VIEWOFTABLE1", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+ assertTableDefinition(conn, "VIEWOFTABLE2", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+
+ // query table
+ ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
+ assertTrue(rs.next());
+ assertEquals("view1", rs.getString("ID"));
+ assertEquals(12, rs.getInt("COL1"));
+ assertEquals(13, rs.getInt("COL2"));
+ assertEquals(14, rs.getInt("VIEW_COL1"));
+ assertEquals("view5", rs.getString("VIEW_COL2"));
+ assertFalse(rs.next());
+ // query both views
+ rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE1");
+ assertTrue(rs.next());
+ assertEquals("view1", rs.getString("ID"));
+ assertEquals(12, rs.getInt("COL1"));
+ assertEquals(13, rs.getInt("COL2"));
+ assertEquals(14, rs.getInt("VIEW_COL1"));
+ assertEquals("view5", rs.getString("VIEW_COL2"));
+ assertFalse(rs.next());
+ rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE2");
+ assertTrue(rs.next());
+ assertEquals("view1", rs.getString("ID"));
+ assertEquals(12, rs.getInt("COL1"));
+ assertEquals(13, rs.getInt("COL2"));
+ assertEquals(14, rs.getInt("VIEW_COL1"));
+ assertEquals("view5", rs.getString("VIEW_COL2"));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
private void assertTableDefinition(Connection conn, String tableName, PTableType tableType, String parentTableName, int sequenceNumber, int columnCount, int baseColumnCount, String... columnName) throws Exception {
PreparedStatement p = conn.prepareStatement("SELECT * FROM SYSTEM.CATALOG WHERE TABLE_NAME=? AND TABLE_TYPE=?");
p.setString(1, tableName);
@@ -2234,10 +2445,8 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
assertEquals(parentTableName, parentTableColumnValue);
assertEquals(tableName, viewColumnValue);
}
- else if (parentTableColumnsMetadata.getColumnName(columnIndex).equals(PhoenixDatabaseMetaData.ORDINAL_POSITION) && parentTableColumnsRs.getString("COLUMN_FAMILY")!=null) {
- // its ok if the ordinal positions don't match for non-pk columns
- }
- else {
+ // its ok if the ordinal positions don't match for non-pk columns
+ else if (!(parentTableColumnsMetadata.getColumnName(columnIndex).equals(PhoenixDatabaseMetaData.ORDINAL_POSITION) && parentTableColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_FAMILY)!=null)) {
fail(parentTableColumnsMetadata.getColumnName(columnIndex) + " of base table " + parentTableColumnValue + " does not match view "+viewColumnValue) ;
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/01b4f605/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
index 1d8af35..3254c2e 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
@@ -537,6 +537,12 @@ public class ViewIT extends BaseViewIT {
} catch (SQLException e) {
assertEquals(CANNOT_MODIFY_VIEW_PK.getErrorCode(), e.getErrorCode());
}
+ ddl = "CREATE VIEW v2 (k3 VARCHAR PRIMARY KEY) AS SELECT * FROM tp WHERE v1 = 1.0";
+ try {
+ conn.createStatement().execute(ddl);
+ } catch (SQLException e) {
+ assertEquals(CANNOT_MODIFY_VIEW_PK.getErrorCode(), e.getErrorCode());
+ }
}
@Test(expected=ColumnAlreadyExistsException.class)
http://git-wip-us.apache.org/repos/asf/phoenix/blob/01b4f605/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index 399d56e..1be0548 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -186,6 +186,7 @@ import org.apache.phoenix.util.ServerUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Objects;
import com.google.common.cache.Cache;
import com.google.common.collect.Lists;
import com.google.protobuf.ByteString;
@@ -1591,17 +1592,11 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
}
- private boolean isValidLengthOrScale(Integer viewColVal, Cell cell) {
- Integer baseColValue = cell.getValueArray()==null ? null :
- PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
- if ( (baseColValue!=null && viewColVal!=null && baseColValue<viewColVal) || // if the base column has a scale/length less then the view column
- (viewColVal==null && baseColValue!=null)) { // or if the view column has no scale/length, but the base column has a scale/length
- return false;
- }
- return true;
+ private boolean isvalidAttribute(Object obj1, Object obj2) {
+ return (obj1!=null && obj1.equals(obj2)) || (obj1==null && obj2==null);
}
- private MetaDataMutationResult addRowsToChildViews(List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
+ private MetaDataMutationResult addRowsToChildViews(PTable table, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, TableViewFinderResult childViewsResult,
Region region, List<RowLock> locks) throws IOException, SQLException {
for (Result viewResult : childViewsResult.getResults()) {
@@ -1623,6 +1618,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
int numColsAddedToView = 0;
short deltaNumPkColsSoFar = 0;
PColumn existingViewColumn = null;
+ List<PColumn> viewPkColumns = Lists.newArrayList(view.getPKColumns());
+ boolean addingPKColumn=false;
for (Mutation m : tableMetadata) {
byte[][] rkmd = new byte[5][];
int pkCount = getVarChars(m.getRow(), rkmd);
@@ -1635,7 +1632,10 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
existingViewColumn = rkmd[FAMILY_NAME_INDEX] == null
? view.getPKColumn(columnName)
: view.getColumnFamily(rkmd[FAMILY_NAME_INDEX]).getColumn(columnName);
- } catch (ColumnNotFoundException e) {
+ }
+ catch (ColumnFamilyNotFoundException e) {
+ }
+ catch (ColumnNotFoundException e) {
} // Ignore - means column family or column name don't exist
Put p = (Put)m;
@@ -1663,6 +1663,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
}
}
+ // if adding a pk column to the base table
if (rkmd[FAMILY_NAME_INDEX] == null && rkmd[COLUMN_NAME_INDEX] != null) {
List<Cell> keySeqCells = viewColumnDefinitionPut.get(
PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
@@ -1675,35 +1676,45 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
}
}
+ List<Cell> sortOrders = viewColumnDefinitionPut.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+ PhoenixDatabaseMetaData.SORT_ORDER_BYTES);
+ SortOrder sortOrder = SortOrder.getDefault();
+ if (sortOrders != null && sortOrders.size() > 0) {
+ Cell cell = sortOrders.get(0);
+ int sortOrderInt = PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
+ sortOrder = SortOrder.fromSystemValue(sortOrderInt);
+ }
+ if (!Objects.equal(sortOrder,existingViewColumn.getSortOrder())) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
+ }
+ viewPkColumns.remove(existingViewColumn);
}
// if there is an existing view column that matches the column being added to the base table and if the column being added has a null
// scale or maxLength, we need to explicitly do a put to set the scale or maxLength to null (in case the view column has the scale or
// max length set)
+ Integer maxLength = null;
List<Cell> columnSizes = viewColumnDefinitionPut.get(
PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES);
if (columnSizes != null && columnSizes.size() > 0) {
Cell cell = columnSizes.get(0);
- if (!isValidLengthOrScale(existingViewColumn.getMaxLength(),cell)) {
- return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
- }
+ maxLength = cell.getValueArray()==null ? null :
+ PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
}
- else if (existingViewColumn.getMaxLength()!=null) {
- viewColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
- PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES, null);
+ if (!Objects.equal(maxLength,existingViewColumn.getMaxLength())) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
}
+ Integer scale = null;
List<Cell> decimalDigits = viewColumnDefinitionPut.get(
PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES);
if (decimalDigits != null && decimalDigits.size() > 0) {
Cell cell = decimalDigits.get(0);
- if (!isValidLengthOrScale(existingViewColumn.getScale(),cell)) {
- return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
- }
+ scale = cell.getValueArray()==null ? null :
+ PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
}
- else if (existingViewColumn.getScale()!=null) {
- viewColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
- PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES, null);
+ if (!Objects.equal(scale,existingViewColumn.getScale())) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
}
}
else {
@@ -1719,6 +1730,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
* If adding a pk column to the base table (and hence the view), see if there are any indexes on
* the view. If yes, then generate puts for the index header row and column rows.
*/
+ addingPKColumn=true;
deltaNumPkColsSoFar++;
for (PTable index : view.getIndexes()) {
int oldNumberOfColsInIndex = index.getColumns().size();
@@ -1807,6 +1819,12 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
}
}
+ // allow adding a pk columns to base table :
+ // 1. if all the view pk columns are exactly the same as the base table pk columns
+ // 2. if we are adding all the existing view pk columns to the base table
+ if (addingPKColumn && !viewPkColumns.equals(table.getPKColumns())) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
+ }
if (deltaNumPkColsSoFar > 0) {
for (PTable index : view.getIndexes()) {
byte[] indexHeaderRowKey = getViewIndexHeaderRowKey(index);
@@ -1919,7 +1937,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
EnvironmentEdgeManager.currentTimeMillis(), null);
} else {
mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getResults().size() * tableMetaData.size());
- MetaDataMutationResult mutationResult = addRowsToChildViews(tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
+ MetaDataMutationResult mutationResult = addRowsToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
childViewsResult, region, locks);
// return if we were not able to add the column successfully
if (mutationResult!=null)
http://git-wip-us.apache.org/repos/asf/phoenix/blob/01b4f605/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 56c1aa2..9ad52a5 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
@@ -2505,7 +2505,7 @@ public class MetaDataClient {
}
long seqNum = table.getSequenceNumber();
if (changingPhoenixTableProperty || columnDefs.size() > 0) {
- seqNum = incrementTableSeqNum(table, statement.getTableType(), 1, isImmutableRows, disableWAL, multiTenant, storeNulls);
+ seqNum = incrementTableSeqNum(table, statement.getTableType(), columnDefs.size(), isImmutableRows, disableWAL, multiTenant, storeNulls);
tableMetaData.addAll(connection.getMutationState().toMutations().next().getSecond());
connection.rollback();
}
@@ -2977,14 +2977,11 @@ public class MetaDataClient {
private boolean isLastPKVariableLength(PTable table) {
List<PColumn> pkColumns = table.getPKColumns();
- if (pkColumns.size() < 1) {
- return false;
- } else {
- return !pkColumns.get(pkColumns.size()-1).getDataType().isFixedWidth();
- }
+ return !pkColumns.get(pkColumns.size()-1).getDataType().isFixedWidth();
}
private PTable getParentOfView(PTable view) throws SQLException {
+ //TODO just use view.getParentName().getString() after implementing https://issues.apache.org/jira/browse/PHOENIX-2114
SelectStatement select = new SQLParser(view.getViewStatement()).parseQuery();
String parentName = SchemaUtil.normalizeFullTableName(select.getFrom().toString().trim());
return connection.getMetaDataCache().getTable(new PTableKey(view.getTenantId(), parentName));
[04/50] [abbrv] phoenix git commit: Merge branch 'master' of
https://git-wip-us.apache.org/repos/asf/phoenix
Posted by ma...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/phoenix
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/ade12a78
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/ade12a78
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/ade12a78
Branch: refs/heads/calcite
Commit: ade12a787401d0bc67feb7e9c9dc171ca6cc27fb
Parents: df42fa1 be5aba5
Author: maryannxue <we...@intel.com>
Authored: Sat Jul 4 13:11:21 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Sat Jul 4 13:11:21 2015 -0400
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/ArrayIT.java | 119 +++++++++++++++++++
.../expression/ArrayConstructorExpression.java | 19 +--
.../org/apache/phoenix/util/PhoenixRuntime.java | 3 +-
.../java/org/apache/phoenix/util/QueryUtil.java | 4 +-
.../org/apache/phoenix/util/SchemaUtil.java | 18 ++-
.../phoenix/pig/PhoenixHBaseLoaderIT.java | 9 +-
.../phoenix/pig/PhoenixHBaseStorerIT.java | 4 +-
.../apache/phoenix/pig/PhoenixHBaseStorage.java | 51 ++++----
8 files changed, 178 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
[33/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java b/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
index 0956753..a12f633 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
@@ -59,14 +59,10 @@ import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
import org.apache.phoenix.hbase.index.util.KeyValueBuilder;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.jdbc.PhoenixStatement;
-import org.apache.phoenix.parse.AndParseNode;
-import org.apache.phoenix.parse.BaseParseNodeVisitor;
-import org.apache.phoenix.parse.BooleanParseNodeVisitor;
import org.apache.phoenix.parse.FunctionParseNode;
import org.apache.phoenix.parse.ParseNode;
import org.apache.phoenix.parse.SQLParser;
import org.apache.phoenix.parse.StatelessTraverseAllParseNodeVisitor;
-import org.apache.phoenix.parse.TraverseAllParseNodeVisitor;
import org.apache.phoenix.parse.UDFParseNode;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.ColumnNotFoundException;
@@ -265,6 +261,7 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
private int[] dataPkPosition;
private int maxTrailingNulls;
private ColumnReference dataEmptyKeyValueRef;
+ private boolean rowKeyOrderOptimizable;
private IndexMaintainer(RowKeySchema dataRowKeySchema, boolean isDataTableSalted) {
this.dataRowKeySchema = dataRowKeySchema;
@@ -273,6 +270,7 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
private IndexMaintainer(PTable dataTable, PTable index, PhoenixConnection connection) {
this(dataTable.getRowKeySchema(), dataTable.getBucketNum() != null);
+ this.rowKeyOrderOptimizable = index.rowKeyOrderOptimizable();
this.isMultiTenant = dataTable.isMultiTenant();
this.viewIndexId = index.getViewIndexId() == null ? null : MetaDataUtil.getViewIndexIdDataType().toBytes(index.getViewIndexId());
this.isLocalIndex = index.getIndexType() == IndexType.LOCAL;
@@ -434,7 +432,7 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
dataRowKeySchema.next(ptr, dataPosOffset, maxRowKeyOffset);
output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
if (!dataRowKeySchema.getField(dataPosOffset).getDataType().isFixedWidth()) {
- output.writeByte(QueryConstants.SEPARATOR_BYTE);
+ output.writeByte(SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, ptr.getLength()==0, dataRowKeySchema.getField(dataPosOffset)));
}
dataPosOffset++;
}
@@ -481,21 +479,22 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
}
boolean isDataColumnInverted = dataSortOrder != SortOrder.ASC;
PDataType indexColumnType = IndexUtil.getIndexColumnDataType(isNullable, dataColumnType);
- boolean isBytesComparable = dataColumnType.isBytesComparableWith(indexColumnType) ;
- if (isBytesComparable && isDataColumnInverted == descIndexColumnBitSet.get(i)) {
+ boolean isBytesComparable = dataColumnType.isBytesComparableWith(indexColumnType);
+ boolean isIndexColumnDesc = descIndexColumnBitSet.get(i);
+ if (isBytesComparable && isDataColumnInverted == isIndexColumnDesc) {
output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
} else {
if (!isBytesComparable) {
indexColumnType.coerceBytes(ptr, dataColumnType, dataSortOrder, SortOrder.getDefault());
}
- if (descIndexColumnBitSet.get(i) != isDataColumnInverted) {
+ if (isDataColumnInverted != isIndexColumnDesc) {
writeInverted(ptr.get(), ptr.getOffset(), ptr.getLength(), output);
} else {
output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
}
}
if (!indexColumnType.isFixedWidth()) {
- output.writeByte(QueryConstants.SEPARATOR_BYTE);
+ output.writeByte(SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, ptr.getLength() == 0, isIndexColumnDesc ? SortOrder.DESC : SortOrder.ASC));
}
}
int length = stream.size();
@@ -545,7 +544,7 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
indexRowKeySchema.next(ptr, indexPosOffset, maxRowKeyOffset);
output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
if (!dataRowKeySchema.getField(dataPosOffset).getDataType().isFixedWidth()) {
- output.writeByte(QueryConstants.SEPARATOR_BYTE);
+ output.writeByte(SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, ptr.getLength() == 0, dataRowKeySchema.getField(dataPosOffset)));
}
indexPosOffset++;
dataPosOffset++;
@@ -587,8 +586,11 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
}
}
}
- if (!dataRowKeySchema.getField(i).getDataType().isFixedWidth() && ((i+1) != dataRowKeySchema.getFieldCount())) {
- output.writeByte(QueryConstants.SEPARATOR_BYTE);
+ // Write separator byte if variable length unless it's the last field in the schema
+ // (but we still need to write it if it's DESC to ensure sort order is correct).
+ byte sepByte = SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, ptr.getLength() == 0, dataRowKeySchema.getField(i));
+ if (!dataRowKeySchema.getField(i).getDataType().isFixedWidth() && (((i+1) != dataRowKeySchema.getFieldCount()) || sepByte == QueryConstants.DESC_SEPARATOR_BYTE)) {
+ output.writeByte(sepByte);
}
}
int length = stream.size();
@@ -658,6 +660,7 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
private RowKeySchema generateIndexRowKeySchema() {
int nIndexedColumns = getIndexPkColumnCount() + (isMultiTenant ? 1 : 0) + (!isLocalIndex && nIndexSaltBuckets > 0 ? 1 : 0) + (viewIndexId != null ? 1 : 0) - getNumViewConstants();
RowKeySchema.RowKeySchemaBuilder builder = new RowKeySchema.RowKeySchemaBuilder(nIndexedColumns);
+ builder.rowKeyOrderOptimizable(rowKeyOrderOptimizable);
if (!isLocalIndex && nIndexSaltBuckets > 0) {
builder.addField(SaltingUtil.SALTING_COLUMN, false, SortOrder.ASC);
nIndexedColumns--;
@@ -708,44 +711,67 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
// same for all rows in this index)
if (!viewConstantColumnBitSet.get(i)) {
int pos = rowKeyMetaData.getIndexPkPosition(i-dataPosOffset);
- indexFields[pos] = dataRowKeySchema.getField(i);
+ Field dataField = dataRowKeySchema.getField(i);
+ indexFields[pos] =
+ dataRowKeySchema.getField(i);
}
}
+ BitSet descIndexColumnBitSet = rowKeyMetaData.getDescIndexColumnBitSet();
Iterator<Expression> expressionItr = indexedExpressions.iterator();
- for (Field indexField : indexFields) {
- if (indexField == null) { // Add field for kv column in index
- final PDataType dataType = expressionItr.next().getDataType();
- builder.addField(new PDatum() {
+ for (int i = 0; i < indexFields.length; i++) {
+ Field indexField = indexFields[i];
+ PDataType dataTypeToBe;
+ SortOrder sortOrderToBe;
+ boolean isNullableToBe;
+ Integer maxLengthToBe;
+ Integer scaleToBe;
+ if (indexField == null) {
+ Expression e = expressionItr.next();
+ isNullableToBe = true;
+ dataTypeToBe = IndexUtil.getIndexColumnDataType(isNullableToBe, e.getDataType());
+ sortOrderToBe = descIndexColumnBitSet.get(i) ? SortOrder.DESC : SortOrder.ASC;
+ maxLengthToBe = e.getMaxLength();
+ scaleToBe = e.getScale();
+ } else {
+ isNullableToBe = indexField.isNullable();
+ dataTypeToBe = IndexUtil.getIndexColumnDataType(isNullableToBe, indexField.getDataType());
+ sortOrderToBe = descIndexColumnBitSet.get(i) ? SortOrder.DESC : SortOrder.ASC;
+ maxLengthToBe = indexField.getMaxLength();
+ scaleToBe = indexField.getScale();
+ }
+ final PDataType dataType = dataTypeToBe;
+ final SortOrder sortOrder = sortOrderToBe;
+ final boolean isNullable = isNullableToBe;
+ final Integer maxLength = maxLengthToBe;
+ final Integer scale = scaleToBe;
+ builder.addField(new PDatum() {
- @Override
- public boolean isNullable() {
- return true;
- }
+ @Override
+ public boolean isNullable() {
+ return isNullable;
+ }
- @Override
- public PDataType getDataType() {
- return IndexUtil.getIndexColumnDataType(true, dataType);
- }
+ @Override
+ public PDataType getDataType() {
+ return dataType;
+ }
- @Override
- public Integer getMaxLength() {
- return null;
- }
+ @Override
+ public Integer getMaxLength() {
+ return maxLength;
+ }
- @Override
- public Integer getScale() {
- return null;
- }
+ @Override
+ public Integer getScale() {
+ return scale;
+ }
- @Override
- public SortOrder getSortOrder() {
- return SortOrder.getDefault();
- }
-
- }, true, SortOrder.getDefault());
- } else { // add field from data row key
- builder.addField(indexField);
- }
+ @Override
+ public SortOrder getSortOrder() {
+ return sortOrder;
+ }
+
+ }, true, sortOrder);
}
return builder.build();
}
@@ -928,9 +954,18 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
byte[] cq = Bytes.readByteArray(input);
coveredColumns.add(new ColumnReference(cf,cq));
}
- indexTableName = Bytes.readByteArray(input);
- dataEmptyKeyValueCF = Bytes.readByteArray(input);
+ // Hack to serialize whether the index row key is optimizable
int len = WritableUtils.readVInt(input);
+ if (len < 0) {
+ rowKeyOrderOptimizable = false;
+ len *= -1;
+ } else {
+ rowKeyOrderOptimizable = true;
+ }
+ indexTableName = new byte[len];
+ input.readFully(indexTableName, 0, len);
+ dataEmptyKeyValueCF = Bytes.readByteArray(input);
+ len = WritableUtils.readVInt(input);
//TODO remove this in the next major release
boolean isNewClient = false;
if (len < 0) {
@@ -1023,7 +1058,9 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
Bytes.writeByteArray(output, ref.getFamily());
Bytes.writeByteArray(output, ref.getQualifier());
}
- Bytes.writeByteArray(output, indexTableName);
+ // TODO: remove when rowKeyOrderOptimizable hack no longer needed
+ WritableUtils.writeVInt(output,indexTableName.length * (rowKeyOrderOptimizable ? 1 : -1));
+ output.write(indexTableName, 0, indexTableName.length);
Bytes.writeByteArray(output, dataEmptyKeyValueCF);
// TODO in order to maintain b/w compatibility encode emptyKeyValueCFPtr.getLength() as a negative value (so we can distinguish between new and old clients)
// when indexedColumnTypes is removed, remove this
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
index cf66d93..a0aefaa 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
@@ -51,6 +51,8 @@ import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.compile.RowProjector;
import org.apache.phoenix.compile.ScanRanges;
import org.apache.phoenix.compile.StatementContext;
+import org.apache.phoenix.coprocessor.BaseScannerRegionObserver;
+import org.apache.phoenix.coprocessor.UngroupedAggregateRegionObserver;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.exception.SQLExceptionInfo;
import org.apache.phoenix.filter.ColumnProjectionFilter;
@@ -67,7 +69,6 @@ import org.apache.phoenix.schema.PColumnFamily;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.PTable.IndexType;
import org.apache.phoenix.schema.PTable.ViewType;
-import org.apache.phoenix.schema.SaltingUtil;
import org.apache.phoenix.schema.StaleRegionBoundaryCacheException;
import org.apache.phoenix.schema.TableRef;
import org.apache.phoenix.schema.stats.GuidePostsInfo;
@@ -134,6 +135,68 @@ public abstract class BaseResultIterators extends ExplainTable implements Result
return true;
}
+ private static void initializeScan(QueryPlan plan, Integer perScanLimit) {
+ StatementContext context = plan.getContext();
+ TableRef tableRef = plan.getTableRef();
+ PTable table = tableRef.getTable();
+ Scan scan = context.getScan();
+
+ Map<byte [], NavigableSet<byte []>> familyMap = scan.getFamilyMap();
+ // Hack for PHOENIX-2067 to force raw scan over all KeyValues to fix their row keys
+ if (context.getConnection().isDescVarLengthRowKeyUpgrade()) {
+ // We project *all* KeyValues across all column families as we make a pass over
+ // a physical table and we want to make sure we catch all KeyValues that may be
+ // dynamic or part of an updatable view.
+ familyMap.clear();
+ scan.setMaxVersions();
+ scan.setFilter(null); // Remove any filter
+ scan.setRaw(true); // Traverse (and subsequently clone) all KeyValues
+ // Pass over PTable so we can re-write rows according to the row key schema
+ scan.setAttribute(BaseScannerRegionObserver.UPGRADE_DESC_ROW_KEY, UngroupedAggregateRegionObserver.serialize(table));
+ } else {
+ FilterableStatement statement = plan.getStatement();
+ RowProjector projector = plan.getProjector();
+ boolean keyOnlyFilter = familyMap.isEmpty() && context.getWhereCoditionColumns().isEmpty();
+ if (projector.isProjectEmptyKeyValue()) {
+ // If nothing projected into scan and we only have one column family, just allow everything
+ // to be projected and use a FirstKeyOnlyFilter to skip from row to row. This turns out to
+ // be quite a bit faster.
+ // Where condition columns also will get added into familyMap
+ // When where conditions are present, we can not add FirstKeyOnlyFilter at beginning.
+ if (familyMap.isEmpty() && context.getWhereCoditionColumns().isEmpty()
+ && table.getColumnFamilies().size() == 1) {
+ // Project the one column family. We must project a column family since it's possible
+ // that there are other non declared column families that we need to ignore.
+ scan.addFamily(table.getColumnFamilies().get(0).getName().getBytes());
+ } else {
+ byte[] ecf = SchemaUtil.getEmptyColumnFamily(table);
+ // Project empty key value unless the column family containing it has
+ // been projected in its entirety.
+ if (!familyMap.containsKey(ecf) || familyMap.get(ecf) != null) {
+ scan.addColumn(ecf, QueryConstants.EMPTY_COLUMN_BYTES);
+ }
+ }
+ } else if (table.getViewType() == ViewType.MAPPED) {
+ // Since we don't have the empty key value in MAPPED tables, we must select all CFs in HRS. But only the
+ // selected column values are returned back to client
+ for (PColumnFamily family : table.getColumnFamilies()) {
+ scan.addFamily(family.getName().getBytes());
+ }
+ }
+ // Add FirstKeyOnlyFilter if there are no references to key value columns
+ if (keyOnlyFilter) {
+ ScanUtil.andFilterAtBeginning(scan, new FirstKeyOnlyFilter());
+ }
+
+ // TODO adding all CFs here is not correct. It should be done only after ColumnProjectionOptimization.
+ if (perScanLimit != null) {
+ ScanUtil.andFilterAtEnd(scan, new PageFilter(perScanLimit));
+ }
+
+ doColumnProjectionOptimization(context, scan, table, statement);
+ }
+ }
+
public BaseResultIterators(QueryPlan plan, Integer perScanLimit, ParallelScanGrouper scanGrouper) throws SQLException {
super(plan.getContext(), plan.getTableRef(), plan.getGroupBy(), plan.getOrderBy(), plan.getStatement().getHint(), plan.getLimit());
this.plan = plan;
@@ -141,52 +204,12 @@ public abstract class BaseResultIterators extends ExplainTable implements Result
StatementContext context = plan.getContext();
TableRef tableRef = plan.getTableRef();
PTable table = tableRef.getTable();
- FilterableStatement statement = plan.getStatement();
- RowProjector projector = plan.getProjector();
physicalTableName = table.getPhysicalName().getBytes();
tableStats = useStats() ? new MetaDataClient(context.getConnection()).getTableStats(table) : PTableStats.EMPTY_STATS;
- Scan scan = context.getScan();
// Used to tie all the scans together during logging
scanId = UUID.randomUUID().toString();
- Map<byte [], NavigableSet<byte []>> familyMap = scan.getFamilyMap();
- boolean keyOnlyFilter = familyMap.isEmpty() && context.getWhereCoditionColumns().isEmpty();
- if (projector.isProjectEmptyKeyValue()) {
- // If nothing projected into scan and we only have one column family, just allow everything
- // to be projected and use a FirstKeyOnlyFilter to skip from row to row. This turns out to
- // be quite a bit faster.
- // Where condition columns also will get added into familyMap
- // When where conditions are present, we can not add FirstKeyOnlyFilter at beginning.
- if (familyMap.isEmpty() && context.getWhereCoditionColumns().isEmpty()
- && table.getColumnFamilies().size() == 1) {
- // Project the one column family. We must project a column family since it's possible
- // that there are other non declared column families that we need to ignore.
- scan.addFamily(table.getColumnFamilies().get(0).getName().getBytes());
- } else {
- byte[] ecf = SchemaUtil.getEmptyColumnFamily(table);
- // Project empty key value unless the column family containing it has
- // been projected in its entirety.
- if (!familyMap.containsKey(ecf) || familyMap.get(ecf) != null) {
- scan.addColumn(ecf, QueryConstants.EMPTY_COLUMN_BYTES);
- }
- }
- } else if (table.getViewType() == ViewType.MAPPED) {
- // Since we don't have the empty key value in MAPPED tables, we must select all CFs in HRS. But only the
- // selected column values are returned back to client
- for (PColumnFamily family : table.getColumnFamilies()) {
- scan.addFamily(family.getName().getBytes());
- }
- }
- // Add FirstKeyOnlyFilter if there are no references to key value columns
- if (keyOnlyFilter) {
- ScanUtil.andFilterAtBeginning(scan, new FirstKeyOnlyFilter());
- }
- // TODO adding all CFs here is not correct. It should be done only after ColumnProjectionOptimization.
- if (perScanLimit != null) {
- ScanUtil.andFilterAtEnd(scan, new PageFilter(perScanLimit));
- }
-
- doColumnProjectionOptimization(context, scan, table, statement);
+ initializeScan(plan, perScanLimit);
this.scans = getParallelScans();
List<KeyRange> splitRanges = Lists.newArrayListWithExpectedSize(scans.size() * ESTIMATED_GUIDEPOSTS_PER_REGION);
@@ -200,7 +223,7 @@ public abstract class BaseResultIterators extends ExplainTable implements Result
this.allFutures = Lists.newArrayListWithExpectedSize(1);
}
- private void doColumnProjectionOptimization(StatementContext context, Scan scan, PTable table, FilterableStatement statement) {
+ private static void doColumnProjectionOptimization(StatementContext context, Scan scan, PTable table, FilterableStatement statement) {
Map<byte[], NavigableSet<byte[]>> familyMap = scan.getFamilyMap();
if (familyMap != null && !familyMap.isEmpty()) {
// columnsTracker contain cf -> qualifiers which should get returned.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java
index 7b7d4dc..d999ecb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/OrderedResultIterator.java
@@ -27,15 +27,17 @@ import java.util.List;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.execute.DescVarLengthFastByteComparisons;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.OrderByExpression;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.SizedUtil;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
-import org.apache.phoenix.expression.Expression;
-import org.apache.phoenix.expression.OrderByExpression;
-import org.apache.phoenix.schema.tuple.Tuple;
-import org.apache.phoenix.util.SizedUtil;
/**
* Result scanner that sorts aggregated rows by columns specified in the ORDER BY clause.
@@ -155,7 +157,12 @@ public class OrderedResultIterator implements PeekingResultIterator {
Ordering<ResultEntry> ordering = null;
int pos = 0;
for (OrderByExpression col : orderByExpressions) {
- Ordering<ImmutableBytesWritable> o = Ordering.from(new ImmutableBytesWritable.Comparator());
+ Expression e = col.getExpression();
+ Comparator<ImmutableBytesWritable> comparator =
+ e.getSortOrder() == SortOrder.DESC && !e.getDataType().isFixedWidth()
+ ? buildDescVarLengthComparator()
+ : new ImmutableBytesWritable.Comparator();
+ Ordering<ImmutableBytesWritable> o = Ordering.from(comparator);
if(!col.isAscending()) o = o.reverse();
o = col.isNullsLast() ? o.nullsLast() : o.nullsFirst();
Ordering<ResultEntry> entryOrdering = o.onResultOf(new NthKey(pos++));
@@ -164,6 +171,23 @@ public class OrderedResultIterator implements PeekingResultIterator {
return ordering;
}
+ /*
+ * Same as regular comparator, but if all the bytes match and the length is
+ * different, returns the longer length as bigger.
+ */
+ private static Comparator<ImmutableBytesWritable> buildDescVarLengthComparator() {
+ return new Comparator<ImmutableBytesWritable>() {
+
+ @Override
+ public int compare(ImmutableBytesWritable o1, ImmutableBytesWritable o2) {
+ return DescVarLengthFastByteComparisons.compareTo(
+ o1.get(), o1.getOffset(), o1.getLength(),
+ o2.get(), o2.getOffset(), o2.getLength());
+ }
+
+ };
+ }
+
@Override
public Tuple next() throws SQLException {
return getResultIterator().next();
@@ -252,13 +276,13 @@ public class OrderedResultIterator implements PeekingResultIterator {
planSteps.add("CLIENT" + (limit == null ? "" : " TOP " + limit + " ROW" + (limit == 1 ? "" : "S")) + " SORTED BY " + orderByExpressions.toString());
}
- @Override
- public String toString() {
- return "OrderedResultIterator [thresholdBytes=" + thresholdBytes
- + ", limit=" + limit + ", delegate=" + delegate
- + ", orderByExpressions=" + orderByExpressions
- + ", estimatedByteSize=" + estimatedByteSize
- + ", resultIterator=" + resultIterator + ", byteSize="
- + byteSize + "]";
- }
+ @Override
+ public String toString() {
+ return "OrderedResultIterator [thresholdBytes=" + thresholdBytes
+ + ", limit=" + limit + ", delegate=" + delegate
+ + ", orderByExpressions=" + orderByExpressions
+ + ", estimatedByteSize=" + estimatedByteSize
+ + ", resultIterator=" + resultIterator + ", byteSize="
+ + byteSize + "]";
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/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 5805999..0cd76fe 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
@@ -140,6 +140,9 @@ public class PhoenixConnection implements Connection, org.apache.phoenix.jdbc.Jd
private Consistency consistency = Consistency.STRONG;
private Map<String, String> customTracingAnnotations = emptyMap();
private final boolean isRequestLevelMetricsEnabled;
+ private final boolean isDescVarLengthRowKeyUpgrade;
+
+
static {
Tracing.addTraceMetricsSource();
}
@@ -150,28 +153,35 @@ public class PhoenixConnection implements Connection, org.apache.phoenix.jdbc.Jd
return props;
}
- public PhoenixConnection(PhoenixConnection connection) throws SQLException {
- this(connection.getQueryServices(), connection.getURL(), connection.getClientInfo(), connection.getMetaDataCache());
+ public PhoenixConnection(PhoenixConnection connection, boolean isDescRowKeyOrderUpgrade) throws SQLException {
+ this(connection.getQueryServices(), connection.getURL(), connection.getClientInfo(), connection.getMetaDataCache(), isDescRowKeyOrderUpgrade);
this.isAutoCommit = connection.isAutoCommit;
this.sampler = connection.sampler;
this.statementExecutionCounter = connection.statementExecutionCounter;
}
+
+ public PhoenixConnection(PhoenixConnection connection) throws SQLException {
+ this(connection, connection.isDescVarLengthRowKeyUpgrade);
+ }
public PhoenixConnection(PhoenixConnection connection, long scn) throws SQLException {
this(connection.getQueryServices(), connection, scn);
- this.sampler = connection.sampler;
- this.statementExecutionCounter = connection.statementExecutionCounter;
}
public PhoenixConnection(ConnectionQueryServices services, PhoenixConnection connection, long scn) throws SQLException {
- this(services, connection.getURL(), newPropsWithSCN(scn,connection.getClientInfo()), connection.getMetaDataCache());
+ this(services, connection.getURL(), newPropsWithSCN(scn,connection.getClientInfo()), connection.getMetaDataCache(), connection.isDescVarLengthRowKeyUpgrade());
this.isAutoCommit = connection.isAutoCommit;
this.sampler = connection.sampler;
this.statementExecutionCounter = connection.statementExecutionCounter;
}
public PhoenixConnection(ConnectionQueryServices services, String url, Properties info, PMetaData metaData) throws SQLException {
+ this(services, url, info, metaData, false);
+ }
+
+ public PhoenixConnection(ConnectionQueryServices services, String url, Properties info, PMetaData metaData, boolean isDescVarLengthRowKeyUpgrade) throws SQLException {
this.url = url;
+ this.isDescVarLengthRowKeyUpgrade = isDescVarLengthRowKeyUpgrade;
// Copy so client cannot change
this.info = info == null ? new Properties() : PropertiesUtil.deepCopy(info);
final PName tenantId = JDBCUtil.getTenantId(url, info);
@@ -887,4 +897,13 @@ public class PhoenixConnection implements Connection, org.apache.phoenix.jdbc.Jd
mutationState.getReadMetricQueue().clearMetrics();
}
}
+
+ /**
+ * 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;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/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 9cd32e8..feb5989 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
@@ -162,6 +162,7 @@ import org.apache.phoenix.util.UpgradeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
@@ -1831,7 +1832,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
* This closes the passed connection.
*/
private PhoenixConnection addColumn(PhoenixConnection oldMetaConnection, String tableName, long timestamp, String columns, boolean addIfNotExists) throws SQLException {
- Properties props = new Properties(oldMetaConnection.getClientInfo());
+ Properties props = PropertiesUtil.deepCopy(oldMetaConnection.getClientInfo());
props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(timestamp));
// Cannot go through DriverManager or you end up in an infinite loop because it'll call init again
PhoenixConnection metaConnection = new PhoenixConnection(this, oldMetaConnection.getURL(), props, oldMetaConnection.getMetaDataCache());
@@ -1970,6 +1971,20 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
*/
logger.debug("No need to run 4.5 upgrade");
}
+ Properties props = PropertiesUtil.deepCopy(metaConnection.getClientInfo());
+ props.remove(PhoenixRuntime.CURRENT_SCN_ATTRIB);
+ props.remove(PhoenixRuntime.TENANT_ID_ATTRIB);
+ PhoenixConnection conn = new PhoenixConnection(ConnectionQueryServicesImpl.this, metaConnection.getURL(), props, metaConnection.getMetaDataCache());
+ try {
+ Set<String> tablesNeedingUpgrade = UpgradeUtil.getPhysicalTablesWithDescVarLengthRowKey(conn);
+ if (!tablesNeedingUpgrade.isEmpty()) {
+ logger.warn("The following tables require upgrade due to a bug causing the row key to be incorrect for descending columns (PHOENIX-2067):\n" + Joiner.on(' ').join(tablesNeedingUpgrade));
+ }
+ } catch (Exception ex) {
+ logger.error("Unable to determine tables requiring upgrade due to PHOENIX-2067", ex);
+ } finally {
+ conn.close();
+ }
}
}
int nSaltBuckets = ConnectionQueryServicesImpl.this.props.getInt(QueryServices.SEQUENCE_SALT_BUCKETS_ATTRIB,
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java b/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
index afcc741..bca55e8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
@@ -17,8 +17,6 @@
*/
package org.apache.phoenix.query;
-import static org.apache.phoenix.query.QueryConstants.SEPARATOR_BYTE_ARRAY;
-
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -394,18 +392,6 @@ public class KeyRange implements Writable {
return lowerRange == KeyRange.EMPTY_RANGE.getLowerRange() && upperRange == KeyRange.EMPTY_RANGE.getUpperRange();
}
- public KeyRange appendSeparator() {
- byte[] lowerBound = getLowerRange();
- byte[] upperBound = getUpperRange();
- if (lowerBound != UNBOUND) {
- lowerBound = ByteUtil.concat(lowerBound, SEPARATOR_BYTE_ARRAY);
- }
- if (upperBound != UNBOUND) {
- upperBound = ByteUtil.concat(upperBound, SEPARATOR_BYTE_ARRAY);
- }
- return getKeyRange(lowerBound, lowerInclusive, upperBound, upperInclusive);
- }
-
/**
* @return list of at least size 1
*/
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
index d095049..92479b3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
@@ -114,6 +114,7 @@ import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
import org.apache.phoenix.schema.MetaDataSplitPolicy;
import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PNameFactory;
+import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.util.ByteUtil;
@@ -163,6 +164,8 @@ public interface QueryConstants {
*/
public static final byte SEPARATOR_BYTE = (byte) 0;
public static final byte[] SEPARATOR_BYTE_ARRAY = new byte[] {SEPARATOR_BYTE};
+ public static final byte DESC_SEPARATOR_BYTE = SortOrder.invert(SEPARATOR_BYTE);
+ public static final byte[] DESC_SEPARATOR_BYTE_ARRAY = new byte[] {DESC_SEPARATOR_BYTE};
public static final String DEFAULT_COPROCESS_PATH = "phoenix.jar";
public final static int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java
index 2a43679..0251da1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java
@@ -241,4 +241,9 @@ public class DelegateTable implements PTable {
public int getBaseColumnCount() {
return delegate.getBaseColumnCount();
}
+
+ @Override
+ public boolean rowKeyOrderOptimizable() {
+ return delegate.rowKeyOrderOptimizable();
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/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 9ad52a5..b1fcf30 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
@@ -189,6 +189,7 @@ import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.ReadOnlyProps;
import org.apache.phoenix.util.SchemaUtil;
import org.apache.phoenix.util.StringUtil;
+import org.apache.phoenix.util.UpgradeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -702,8 +703,13 @@ public class MetaDataClient {
sortOrder = pkSortOrder.getSecond();
}
}
-
String columnName = columnDefName.getColumnName();
+ if (isPK && sortOrder == SortOrder.DESC && def.getDataType() == PVarbinary.INSTANCE) {
+ throw new SQLExceptionInfo.Builder(SQLExceptionCode.DESC_VARBINARY_NOT_SUPPORTED)
+ .setColumnName(columnName)
+ .build().buildException();
+ }
+
PName familyName = null;
if (def.isPK() && !pkConstraint.getColumnNames().isEmpty() ) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.PRIMARY_KEY_ALREADY_EXISTS)
@@ -1432,6 +1438,8 @@ public class MetaDataClient {
String parentTableName = null;
PName tenantId = connection.getTenantId();
String tenantIdStr = tenantId == null ? null : connection.getTenantId().getString();
+ Long scn = connection.getSCN();
+ long clientTimeStamp = scn == null ? HConstants.LATEST_TIMESTAMP : scn;
boolean multiTenant = false;
boolean storeNulls = false;
Integer saltBucketNum = null;
@@ -1439,6 +1447,7 @@ public class MetaDataClient {
boolean isImmutableRows = false;
List<PName> physicalNames = Collections.emptyList();
boolean addSaltColumn = false;
+ boolean rowKeyOrderOptimizable = true;
if (parent != null && tableType == PTableType.INDEX) {
// Index on view
// TODO: Can we support a multi-tenant index directly on a multi-tenant
@@ -1464,7 +1473,7 @@ public class MetaDataClient {
parentTableName = parent.getTableName().getString();
// Pass through data table sequence number so we can check it hasn't changed
PreparedStatement incrementStatement = connection.prepareStatement(INCREMENT_SEQ_NUM);
- incrementStatement.setString(1, connection.getTenantId() == null ? null : connection.getTenantId().getString());
+ incrementStatement.setString(1, tenantIdStr);
incrementStatement.setString(2, schemaName);
incrementStatement.setString(3, parentTableName);
incrementStatement.setLong(4, parent.getSequenceNumber());
@@ -1476,7 +1485,7 @@ public class MetaDataClient {
// Add row linking from data table row to index table row
PreparedStatement linkStatement = connection.prepareStatement(CREATE_LINK);
- linkStatement.setString(1, connection.getTenantId() == null ? null : connection.getTenantId().getString());
+ linkStatement.setString(1, tenantIdStr);
linkStatement.setString(2, schemaName);
linkStatement.setString(3, parentTableName);
linkStatement.setString(4, tableName);
@@ -1589,6 +1598,12 @@ public class MetaDataClient {
} else {
// Propagate property values to VIEW.
// TODO: formalize the known set of these properties
+ // Manually transfer the ROW_KEY_ORDER_OPTIMIZABLE_BYTES from parent as we don't
+ // want to add this hacky flag to the schema (see PHOENIX-2067).
+ rowKeyOrderOptimizable = parent.rowKeyOrderOptimizable();
+ if (rowKeyOrderOptimizable) {
+ UpgradeUtil.addRowKeyOrderOptimizableCell(tableMetaData, SchemaUtil.getTableKey(tenantIdStr, schemaName, tableName), clientTimeStamp);
+ }
multiTenant = parent.isMultiTenant();
saltBucketNum = parent.getBucketNum();
isImmutableRows = parent.isImmutableRows();
@@ -1606,7 +1621,7 @@ public class MetaDataClient {
// FIXME: not currently used, but see PHOENIX-1367
// as fixing that will require it's usage.
PreparedStatement linkStatement = connection.prepareStatement(CREATE_VIEW_LINK);
- linkStatement.setString(1, connection.getTenantId() == null ? null : connection.getTenantId().getString());
+ linkStatement.setString(1, tenantIdStr);
linkStatement.setString(2, schemaName);
linkStatement.setString(3, tableName);
linkStatement.setString(4, parent.getName().getString());
@@ -1629,7 +1644,7 @@ public class MetaDataClient {
// Add row linking from data table row to physical table row
PreparedStatement linkStatement = connection.prepareStatement(CREATE_LINK);
for (PName physicalName : physicalNames) {
- linkStatement.setString(1, connection.getTenantId() == null ? null : connection.getTenantId().getString());
+ linkStatement.setString(1, tenantIdStr);
linkStatement.setString(2, schemaName);
linkStatement.setString(3, tableName);
linkStatement.setString(4, physicalName.getString());
@@ -1788,7 +1803,7 @@ public class MetaDataClient {
Collections.<PTable>emptyList(), isImmutableRows,
Collections.<PName>emptyList(), defaultFamilyName == null ? null :
PNameFactory.newName(defaultFamilyName), null,
- Boolean.TRUE.equals(disableWAL), false, false, null, indexId, indexType);
+ Boolean.TRUE.equals(disableWAL), false, false, null, indexId, indexType, true);
connection.addTable(table);
} else if (tableType == PTableType.INDEX && indexId == null) {
if (tableProps.get(HTableDescriptor.MAX_FILESIZE) == null) {
@@ -1942,7 +1957,7 @@ public class MetaDataClient {
PTable.INITIAL_SEQ_NUM, pkName == null ? null : PNameFactory.newName(pkName), saltBucketNum, columns,
dataTableName == null ? null : newSchemaName, dataTableName == null ? null : PNameFactory.newName(dataTableName), Collections.<PTable>emptyList(), isImmutableRows,
physicalNames, defaultFamilyName == null ? null : PNameFactory.newName(defaultFamilyName), viewStatement, Boolean.TRUE.equals(disableWAL), multiTenant, storeNulls, viewType,
- indexId, indexType);
+ indexId, indexType, rowKeyOrderOptimizable);
result = new MetaDataMutationResult(code, result.getMutationTime(), table, true);
addTableToCache(result);
return table;
@@ -2889,6 +2904,8 @@ public class MetaDataClient {
if (code == MutationCode.TABLE_ALREADY_EXISTS) {
if (result.getTable() != null) { // To accommodate connection-less update of index state
addTableToCache(result);
+ // Set so that we get the table below with the potentially modified rowKeyOrderOptimizable flag set
+ indexRef.setTable(result.getTable());
}
}
if (newIndexState == PIndexState.BUILDING) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java
index b983074..8da2206 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java
@@ -323,4 +323,13 @@ public interface PTable extends PMetaDataEntity {
IndexType getIndexType();
PTableStats getTableStats();
int getBaseColumnCount();
+
+ /**
+ * Determines whether or not we may optimize out an ORDER BY or do a GROUP BY
+ * in-place when the optimizer tells us it's possible. This is due to PHOENIX-2067
+ * and only applicable for tables using DESC primary key column(s) which have
+ * not been upgraded.
+ * @return true if optimizations row key order optimizations are possible
+ */
+ boolean rowKeyOrderOptimizable();
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
index a947bfc..1756c2f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
@@ -19,7 +19,6 @@ package org.apache.phoenix.schema;
import static org.apache.phoenix.hbase.index.util.KeyValueBuilder.addQuietly;
import static org.apache.phoenix.hbase.index.util.KeyValueBuilder.deleteQuietly;
-import static org.apache.phoenix.query.QueryConstants.SEPARATOR_BYTE;
import static org.apache.phoenix.schema.SaltingUtil.SALTING_COLUMN;
import java.io.IOException;
@@ -126,6 +125,8 @@ public class PTableImpl implements PTable {
private IndexType indexType;
private PTableStats tableStats = PTableStats.EMPTY_STATS;
private int baseColumnCount;
+ private boolean hasDescVarLengthColumns;
+ private boolean rowKeyOrderOptimizable;
public PTableImpl() {
this.indexes = Collections.emptyList();
@@ -195,7 +196,8 @@ public class PTableImpl implements PTable {
table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), timeStamp,
table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), getColumnsToClone(table), parentSchemaName, table.getParentTableName(),
indexes, table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), viewStatement,
- table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(), table.getBaseColumnCount());
+ table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(),
+ table.getTableStats(), table.getBaseColumnCount(), table.rowKeyOrderOptimizable());
}
public static PTableImpl makePTable(PTable table, List<PColumn> columns) throws SQLException {
@@ -203,7 +205,8 @@ public class PTableImpl implements PTable {
table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), table.getTimeStamp(),
table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(),
table.getIndexes(), table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(),
- table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(), table.getBaseColumnCount());
+ table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(),
+ table.getTableStats(), table.getBaseColumnCount(), table.rowKeyOrderOptimizable());
}
public static PTableImpl makePTable(PTable table, long timeStamp, long sequenceNumber, List<PColumn> columns) throws SQLException {
@@ -211,7 +214,8 @@ public class PTableImpl implements PTable {
table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), timeStamp,
sequenceNumber, table.getPKName(), table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(),
table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(), table.isWALDisabled(),
- table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(), table.getBaseColumnCount());
+ table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(),
+ table.getBaseColumnCount(), table.rowKeyOrderOptimizable());
}
public static PTableImpl makePTable(PTable table, long timeStamp, long sequenceNumber, List<PColumn> columns, boolean isImmutableRows) throws SQLException {
@@ -219,7 +223,8 @@ public class PTableImpl implements PTable {
table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), timeStamp,
sequenceNumber, table.getPKName(), table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(),
table.getIndexes(), isImmutableRows, table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(),
- table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(), table.getBaseColumnCount());
+ table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(),
+ table.getIndexType(), table.getTableStats(), table.getBaseColumnCount(), table.rowKeyOrderOptimizable());
}
public static PTableImpl makePTable(PTable table, long timeStamp, long sequenceNumber, List<PColumn> columns, boolean isImmutableRows, boolean isWalDisabled, boolean isMultitenant, boolean storeNulls) throws SQLException {
@@ -227,7 +232,8 @@ public class PTableImpl implements PTable {
table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), timeStamp,
sequenceNumber, table.getPKName(), table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(),
table.getIndexes(), isImmutableRows, table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(),
- isWalDisabled, isMultitenant, storeNulls, table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(), table.getBaseColumnCount());
+ isWalDisabled, isMultitenant, storeNulls, table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(),
+ table.getBaseColumnCount(), table.rowKeyOrderOptimizable());
}
public static PTableImpl makePTable(PTable table, PIndexState state) throws SQLException {
@@ -236,7 +242,18 @@ public class PTableImpl implements PTable {
table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), getColumnsToClone(table),
table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(),
table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(),
- table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(), table.getBaseColumnCount());
+ table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(),
+ table.getTableStats(), table.getBaseColumnCount(), table.rowKeyOrderOptimizable());
+ }
+
+ public static PTableImpl makePTable(PTable table, boolean rowKeyOrderOptimizable) throws SQLException {
+ return new PTableImpl(
+ table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), table.getTimeStamp(),
+ table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), getColumnsToClone(table),
+ table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(),
+ table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(),
+ table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats(),
+ table.getBaseColumnCount(), rowKeyOrderOptimizable);
}
public static PTableImpl makePTable(PTable table, PTableStats stats) throws SQLException {
@@ -245,28 +262,29 @@ public class PTableImpl implements PTable {
table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), getColumnsToClone(table),
table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(),
table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(),
- table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), stats, table.getBaseColumnCount());
+ table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), stats,
+ table.getBaseColumnCount(), table.rowKeyOrderOptimizable());
}
public static PTableImpl makePTable(PName tenantId, PName schemaName, PName tableName, PTableType type, PIndexState state, long timeStamp, long sequenceNumber,
PName pkName, Integer bucketNum, List<PColumn> columns, PName dataSchemaName, PName dataTableName, List<PTable> indexes,
boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression, boolean disableWAL, boolean multiTenant,
- boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType) throws SQLException {
+ boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType, boolean rowKeyOrderOptimizable) throws SQLException {
return new PTableImpl(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName, bucketNum, columns, dataSchemaName,
dataTableName, indexes, isImmutableRows, physicalNames, defaultFamilyName,
viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId,
- indexType, PTableStats.EMPTY_STATS, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT);
+ indexType, PTableStats.EMPTY_STATS, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, rowKeyOrderOptimizable);
}
public static PTableImpl makePTable(PName tenantId, PName schemaName, PName tableName, PTableType type,
PIndexState state, long timeStamp, long sequenceNumber, PName pkName, Integer bucketNum,
List<PColumn> columns, PName dataSchemaName, PName dataTableName, List<PTable> indexes,
boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression,
- boolean disableWAL, boolean multiTenant, boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType, @NotNull PTableStats stats, int baseColumnCount)
+ boolean disableWAL, boolean multiTenant, boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType, @NotNull PTableStats stats, int baseColumnCount, boolean rowKeyOrderOptimizable)
throws SQLException {
return new PTableImpl(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName,
bucketNum, columns, dataSchemaName, dataTableName, indexes, isImmutableRows, physicalNames,
- defaultFamilyName, viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, stats, baseColumnCount);
+ defaultFamilyName, viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, stats, baseColumnCount, rowKeyOrderOptimizable);
}
private PTableImpl(PName tenantId, PName schemaName, PName tableName, PTableType type, PIndexState state,
@@ -274,10 +292,10 @@ public class PTableImpl implements PTable {
PName parentSchemaName, PName parentTableName, List<PTable> indexes, boolean isImmutableRows,
List<PName> physicalNames, PName defaultFamilyName, String viewExpression, boolean disableWAL, boolean multiTenant,
boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType,
- PTableStats stats, int baseColumnCount) throws SQLException {
+ PTableStats stats, int baseColumnCount, boolean rowKeyOrderOptimizable) throws SQLException {
init(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName, bucketNum, columns,
stats, schemaName, parentTableName, indexes, isImmutableRows, physicalNames, defaultFamilyName,
- viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, baseColumnCount);
+ viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, baseColumnCount, rowKeyOrderOptimizable);
}
@Override
@@ -305,7 +323,7 @@ public class PTableImpl implements PTable {
PName pkName, Integer bucketNum, List<PColumn> columns, PTableStats stats, PName parentSchemaName, PName parentTableName,
List<PTable> indexes, boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression, boolean disableWAL,
boolean multiTenant, boolean storeNulls, ViewType viewType, Short viewIndexId,
- IndexType indexType , int baseColumnCount) throws SQLException {
+ IndexType indexType , int baseColumnCount, boolean rowKeyOrderOptimizable) throws SQLException {
Preconditions.checkNotNull(schemaName);
Preconditions.checkArgument(tenantId==null || tenantId.getBytes().length > 0); // tenantId should be null or not empty
int estimatedSize = SizedUtil.OBJECT_SIZE * 2 + 23 * SizedUtil.POINTER_SIZE + 4 * SizedUtil.INT_SIZE + 2 * SizedUtil.LONG_SIZE + 2 * SizedUtil.INT_OBJECT_SIZE +
@@ -335,6 +353,7 @@ public class PTableImpl implements PTable {
this.viewIndexId = viewIndexId;
this.indexType = indexType;
this.tableStats = stats;
+ this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
List<PColumn> pkColumns;
PColumn[] allColumns;
@@ -386,7 +405,8 @@ public class PTableImpl implements PTable {
for (PColumn column : allColumns) {
PName familyName = column.getFamilyName();
if (familyName == null) {
- pkColumns.add(column);
+ hasDescVarLengthColumns |= (column.getSortOrder() == SortOrder.DESC && !column.getDataType().isFixedWidth());
+ pkColumns.add(column);
}
if (familyName == null) {
estimatedSize += column.getEstimatedSize(); // PK columns
@@ -401,6 +421,7 @@ public class PTableImpl implements PTable {
}
}
this.pkColumns = ImmutableList.copyOf(pkColumns);
+ builder.rowKeyOrderOptimizable(this.rowKeyOrderOptimizable()); // after hasDescVarLengthColumns is calculated
this.rowKeySchema = builder.build();
estimatedSize += rowKeySchema.getEstimatedSize();
Iterator<Map.Entry<PName,List<PColumn>>> iterator = familyMap.entrySet().iterator();
@@ -500,18 +521,22 @@ public class PTableImpl implements PTable {
List<PColumn> columns = getPKColumns();
int nColumns = columns.size();
PDataType type = null;
+ SortOrder sortOrder = null;
+ boolean wasNull = false;
while (i < nValues && i < nColumns) {
// Separate variable length column values in key with zero byte
if (type != null && !type.isFixedWidth()) {
- os.write(SEPARATOR_BYTE);
+ os.write(SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable(), wasNull, sortOrder));
}
PColumn column = columns.get(i);
+ sortOrder = column.getSortOrder();
type = column.getDataType();
// This will throw if the value is null and the type doesn't allow null
byte[] byteValue = values[i++];
if (byteValue == null) {
byteValue = ByteUtil.EMPTY_BYTE_ARRAY;
}
+ wasNull = byteValue.length == 0;
// An empty byte array return value means null. Do this,
// since a type may have muliple representations of null.
// For example, VARCHAR treats both null and an empty string
@@ -529,11 +554,14 @@ public class PTableImpl implements PTable {
}
os.write(byteValue, 0, byteValue.length);
}
+ // Need trailing byte for DESC columns
+ if (type != null && !type.isFixedWidth() && SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable(), wasNull, sortOrder) == QueryConstants.DESC_SEPARATOR_BYTE) {
+ os.write(QueryConstants.DESC_SEPARATOR_BYTE);
+ }
// If some non null pk values aren't set, then throw
if (i < nColumns) {
PColumn column = columns.get(i);
- type = column.getDataType();
- if (type.isFixedWidth() || !column.isNullable()) {
+ if (column.getDataType().isFixedWidth() || !column.isNullable()) {
throw new ConstraintViolationException(name.getString() + "." + column.getName().getString() + " may not be null");
}
}
@@ -977,12 +1005,16 @@ public class PTableImpl implements PTable {
baseColumnCount = table.getBaseColumnCount();
}
+ boolean rowKeyOrderOptimizable = false;
+ if (table.hasRowKeyOrderOptimizable()) {
+ rowKeyOrderOptimizable = table.getRowKeyOrderOptimizable();
+ }
try {
PTableImpl result = new PTableImpl();
result.init(tenantId, schemaName, tableName, tableType, indexState, timeStamp, sequenceNumber, pkName,
(bucketNum == NO_SALTING) ? null : bucketNum, columns, stats, schemaName,dataTableName, indexes,
isImmutableRows, physicalNames, defaultFamilyName, viewStatement, disableWAL,
- multiTenant, storeNulls, viewType, viewIndexId, indexType, baseColumnCount);
+ multiTenant, storeNulls, viewType, viewIndexId, indexType, baseColumnCount, rowKeyOrderOptimizable);
return result;
} catch (SQLException e) {
throw new RuntimeException(e); // Impossible
@@ -1072,6 +1104,7 @@ public class PTableImpl implements PTable {
}
}
builder.setBaseColumnCount(table.getBaseColumnCount());
+ builder.setRowKeyOrderOptimizable(table.rowKeyOrderOptimizable());
return builder.build();
}
@@ -1095,4 +1128,9 @@ public class PTableImpl implements PTable {
public int getBaseColumnCount() {
return baseColumnCount;
}
+
+ @Override
+ public boolean rowKeyOrderOptimizable() {
+ return rowKeyOrderOptimizable || !hasDescVarLengthColumns;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeySchema.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeySchema.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeySchema.java
index e5aa571..9d86dd6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeySchema.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeySchema.java
@@ -17,13 +17,12 @@
*/
package org.apache.phoenix.schema;
-import static org.apache.phoenix.query.QueryConstants.SEPARATOR_BYTE;
-
import java.util.Collections;
import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.util.SchemaUtil;
/**
@@ -37,17 +36,19 @@ import org.apache.phoenix.query.QueryConstants;
* @since 0.1
*/
public class RowKeySchema extends ValueSchema {
- public static final RowKeySchema EMPTY_SCHEMA = new RowKeySchema(0,Collections.<Field>emptyList())
+ public static final RowKeySchema EMPTY_SCHEMA = new RowKeySchema(0,Collections.<Field>emptyList(), true)
;
public RowKeySchema() {
}
- protected RowKeySchema(int minNullable, List<Field> fields) {
- super(minNullable, fields);
+ protected RowKeySchema(int minNullable, List<Field> fields, boolean rowKeyOrderOptimizable) {
+ super(minNullable, fields, rowKeyOrderOptimizable);
}
public static class RowKeySchemaBuilder extends ValueSchemaBuilder {
+ private boolean rowKeyOrderOptimizable = false;
+
public RowKeySchemaBuilder(int maxFields) {
super(maxFields);
setMaxFields(maxFields);
@@ -59,13 +60,22 @@ public class RowKeySchema extends ValueSchema {
return this;
}
+ public RowKeySchemaBuilder rowKeyOrderOptimizable(boolean rowKeyOrderOptimizable) {
+ this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
+ return this;
+ }
+
@Override
public RowKeySchema build() {
List<Field> condensedFields = buildFields();
- return new RowKeySchema(this.minNullable, condensedFields);
+ return new RowKeySchema(this.minNullable, condensedFields, rowKeyOrderOptimizable);
}
}
+ public boolean rowKeyOrderOptimizable() {
+ return rowKeyOrderOptimizable;
+ }
+
public int getMaxFields() {
return this.getMinNullable();
}
@@ -148,13 +158,19 @@ public class RowKeySchema extends ValueSchema {
if (field.getDataType().isFixedWidth()) {
ptr.set(ptr.get(),ptr.getOffset(), field.getByteSize());
} else {
- if (position+1 == getFieldCount() ) { // Last field has no terminator
- ptr.set(ptr.get(), ptr.getOffset(), maxOffset - ptr.getOffset());
+ if (position+1 == getFieldCount() ) {
+ // Last field has no terminator unless it's descending sort order
+ int len = maxOffset - ptr.getOffset();
+ ptr.set(ptr.get(), ptr.getOffset(), maxOffset - ptr.getOffset() - (SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, len == 0, field) == QueryConstants.DESC_SEPARATOR_BYTE ? 1 : 0));
} else {
byte[] buf = ptr.get();
int offset = ptr.getOffset();
- while (offset < maxOffset && buf[offset] != SEPARATOR_BYTE) {
- offset++;
+ // First byte
+ if (offset < maxOffset && buf[offset] != QueryConstants.SEPARATOR_BYTE) {
+ byte sepByte = SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, false, field);
+ do {
+ offset++;
+ } while (offset < maxOffset && buf[offset] != sepByte);
}
ptr.set(buf, ptr.getOffset(), offset - ptr.getOffset());
}
@@ -204,8 +220,12 @@ public class RowKeySchema extends ValueSchema {
if (!field.getDataType().isFixedWidth()) {
byte[] buf = ptr.get();
int offset = ptr.getOffset()-1-offsetAdjustment;
- while (offset > minOffset /* sanity check*/ && buf[offset] != QueryConstants.SEPARATOR_BYTE) {
- offset--;
+ // Separator always zero byte if zero length
+ if (offset > minOffset && buf[offset] != QueryConstants.SEPARATOR_BYTE) {
+ byte sepByte = SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, false, field);
+ do {
+ offset--;
+ } while (offset > minOffset && buf[offset] != sepByte);
}
if (offset == minOffset) { // shouldn't happen
ptr.set(buf, minOffset, ptr.getOffset()-minOffset-1);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeyValueAccessor.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeyValueAccessor.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeyValueAccessor.java
index 03b2e6a..2a59e01 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeyValueAccessor.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/RowKeyValueAccessor.java
@@ -17,8 +17,6 @@
*/
package org.apache.phoenix.schema;
-import static org.apache.phoenix.query.QueryConstants.SEPARATOR_BYTE;
-
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -28,6 +26,7 @@ import java.util.List;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableUtils;
+import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.util.ByteUtil;
@@ -150,6 +149,9 @@ public class RowKeyValueAccessor implements Writable {
ByteUtil.serializeVIntArray(output, offsets, length);
}
+ private static boolean isSeparatorByte(byte b) {
+ return b == QueryConstants.SEPARATOR_BYTE || b == QueryConstants.DESC_SEPARATOR_BYTE;
+ }
/**
* Calculate the byte offset in the row key to the start of the PK column value
* @param keyBuffer the byte array of the row key
@@ -164,7 +166,7 @@ public class RowKeyValueAccessor implements Writable {
} else { // Else, a negative offset is the number of variable length values to skip
while (offset++ < 0) {
// FIXME: keyOffset < keyBuffer.length required because HBase passes bogus keys to filter to position scan (HBASE-6562)
- while (keyOffset < keyBuffer.length && keyBuffer[keyOffset++] != SEPARATOR_BYTE) {
+ while (keyOffset < keyBuffer.length && !isSeparatorByte(keyBuffer[keyOffset++])) {
}
}
}
@@ -181,11 +183,11 @@ public class RowKeyValueAccessor implements Writable {
*/
public int getLength(byte[] keyBuffer, int keyOffset, int maxOffset) {
if (!hasSeparator) {
- return maxOffset - keyOffset;
+ return maxOffset - keyOffset - (keyBuffer[maxOffset-1] == QueryConstants.DESC_SEPARATOR_BYTE ? 1 : 0);
}
int offset = keyOffset;
// FIXME: offset < maxOffset required because HBase passes bogus keys to filter to position scan (HBASE-6562)
- while (offset < maxOffset && keyBuffer[offset] != SEPARATOR_BYTE) {
+ while (offset < maxOffset && !isSeparatorByte(keyBuffer[offset])) {
offset++;
}
return offset - keyOffset;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/ValueSchema.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/ValueSchema.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/ValueSchema.java
index 7660ffe..a4b40f3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/ValueSchema.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/ValueSchema.java
@@ -49,12 +49,20 @@ public abstract class ValueSchema implements Writable {
private boolean isFixedLength;
private boolean isMaxLength;
private int minNullable;
+ // Only applicable for RowKeySchema (and only due to PHOENIX-2067), but
+ // added here as this is where serialization is done (and we need to
+ // maintain the same serialization shape for b/w compat).
+ protected boolean rowKeyOrderOptimizable;
public ValueSchema() {
}
protected ValueSchema(int minNullable, List<Field> fields) {
- init(minNullable, fields);
+ this(minNullable, fields, true);
+ }
+
+ protected ValueSchema(int minNullable, List<Field> fields, boolean rowKeyOrderOptimizable) {
+ init(minNullable, fields, rowKeyOrderOptimizable);
}
@Override
@@ -68,7 +76,8 @@ public abstract class ValueSchema implements Writable {
SizedUtil.ARRAY_SIZE + count * Field.ESTIMATED_SIZE + SizedUtil.sizeOfArrayList(count);
}
- private void init(int minNullable, List<Field> fields) {
+ private void init(int minNullable, List<Field> fields, boolean rowKeyOrderOptimizable) {
+ this.rowKeyOrderOptimizable = rowKeyOrderOptimizable;
this.minNullable = minNullable;
this.fields = ImmutableList.copyOf(fields);
int estimatedLength = 0;
@@ -324,14 +333,6 @@ public abstract class ValueSchema implements Writable {
return size;
}
- public void serialize(DataOutput output) throws IOException {
- WritableUtils.writeVInt(output, minNullable);
- WritableUtils.writeVInt(output, fields.size());
- for (int i = 0; i < fields.size(); i++) {
- fields.get(i).write(output);
- }
- }
-
public Field getField(int position) {
return fields.get(fieldIndexByPosition[position]);
}
@@ -366,19 +367,24 @@ public abstract class ValueSchema implements Writable {
public void readFields(DataInput in) throws IOException {
int minNullable = WritableUtils.readVInt(in);
int nFields = WritableUtils.readVInt(in);
+ boolean rowKeyOrderOptimizable = false;
+ if (nFields < 0) {
+ rowKeyOrderOptimizable = true;
+ nFields *= -1;
+ }
List<Field> fields = Lists.newArrayListWithExpectedSize(nFields);
for (int i = 0; i < nFields; i++) {
Field field = new Field();
field.readFields(in);
fields.add(field);
}
- init(minNullable, fields);
+ init(minNullable, fields, rowKeyOrderOptimizable);
}
@Override
public void write(DataOutput out) throws IOException {
WritableUtils.writeVInt(out, minNullable);
- WritableUtils.writeVInt(out, fields.size());
+ WritableUtils.writeVInt(out, fields.size() * (rowKeyOrderOptimizable ? -1 : 1));
for (int i = 0; i < fields.size(); i++) {
fields.get(i).write(out);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java
index ebb7d1f..e692470 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java
@@ -60,10 +60,10 @@ public class StatisticsUtil {
int offset = 0;
System.arraycopy(table, 0, rowKey, offset, table.length);
offset += table.length;
- rowKey[offset++] = QueryConstants.SEPARATOR_BYTE;
+ rowKey[offset++] = QueryConstants.SEPARATOR_BYTE; // assumes stats table columns not DESC
System.arraycopy(fam.get(), fam.getOffset(), rowKey, offset, fam.getLength());
offset += fam.getLength();
- rowKey[offset++] = QueryConstants.SEPARATOR_BYTE;
+ rowKey[offset++] = QueryConstants.SEPARATOR_BYTE; // assumes stats table columns not DESC
System.arraycopy(region, 0, rowKey, offset, region.length);
return rowKey;
}
[29/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimestampArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimestampArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimestampArray.java
index 1159b5c..3407310 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimestampArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimestampArray.java
@@ -17,94 +17,80 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.phoenix.schema.SortOrder;
+import java.sql.Timestamp;
-import java.sql.*;
+import org.apache.phoenix.schema.SortOrder;
public class PUnsignedTimestampArray extends PArrayDataType<Timestamp[]> {
- public static final PUnsignedTimestampArray INSTANCE = new PUnsignedTimestampArray();
-
- private PUnsignedTimestampArray() {
- super("UNSIGNED_TIMESTAMP ARRAY",
- PDataType.ARRAY_TYPE_BASE + PUnsignedTimestamp.INSTANCE.getSqlType(), PhoenixArray.class,
- null, 37);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedTimestampArray INSTANCE = new PUnsignedTimestampArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedTimestampArray() {
+ super("UNSIGNED_TIMESTAMP ARRAY",
+ PDataType.ARRAY_TYPE_BASE + PUnsignedTimestamp.INSTANCE.getSqlType(), PhoenixArray.class,
+ null, 37);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedTimestamp.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedTimestamp.INSTANCE, sortOrder,
- maxLength, scale, PUnsignedTimestamp.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedTimestamp.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] timeStampArr = (Object[]) pArr.array;
- for (Object i : timeStampArr) {
- if (!super.isCoercibleTo(PUnsignedTimestamp.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedTimestamp.INSTANCE, sortOrder,
+ maxLength, scale, PUnsignedTimestamp.INSTANCE);
}
- return true;
- }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] timeStampArr = (Object[]) pArr.array;
+ for (Object i : timeStampArr) {
+ if (!super.isCoercibleTo(PUnsignedTimestamp.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedTimestamp.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedTimestamp.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyintArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyintArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyintArray.java
index a73f284..6843340 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyintArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyintArray.java
@@ -17,94 +17,78 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PUnsignedTinyintArray extends PArrayDataType<byte[]> {
- public static final PUnsignedTinyintArray INSTANCE = new PUnsignedTinyintArray();
-
- private PUnsignedTinyintArray() {
- super("UNSIGNED_TINYINT ARRAY",
- PDataType.ARRAY_TYPE_BASE + PUnsignedTinyint.INSTANCE.getSqlType(), PhoenixArray.class,
- null, 45);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedTinyintArray INSTANCE = new PUnsignedTinyintArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedTinyintArray() {
+ super("UNSIGNED_TINYINT ARRAY",
+ PDataType.ARRAY_TYPE_BASE + PUnsignedTinyint.INSTANCE.getSqlType(), PhoenixArray.class,
+ null, 45);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedTinyint.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedTinyint.INSTANCE, sortOrder, maxLength,
- scale, PUnsignedTinyint.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedTinyint.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] byteArr = (Object[]) pArr.array;
- for (Object i : byteArr) {
- if (!super.isCoercibleTo(PUnsignedTinyint.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedTinyint.INSTANCE, sortOrder, maxLength,
+ scale, PUnsignedTinyint.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] byteArr = (Object[]) pArr.array;
+ for (Object i : byteArr) {
+ if (!super.isCoercibleTo(PUnsignedTinyint.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedTinyint.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedTinyint.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinaryArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinaryArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinaryArray.java
index 10448ac..01b8667 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinaryArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarbinaryArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PVarbinaryArray extends PArrayDataType<byte[][]> {
- public static final PVarbinaryArray INSTANCE = new PVarbinaryArray();
-
- private PVarbinaryArray() {
- super("VARBINARY ARRAY", PDataType.ARRAY_TYPE_BASE + PVarbinary.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 27);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PVarbinaryArray INSTANCE = new PVarbinaryArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PVarbinaryArray() {
+ super("VARBINARY ARRAY", PDataType.ARRAY_TYPE_BASE + PVarbinary.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 27);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PVarbinary.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PVarbinary.INSTANCE, sortOrder, maxLength, scale,
- PVarbinary.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PVarbinary.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] charArr = (Object[]) pArr.array;
- for (Object i : charArr) {
- if (!super.isCoercibleTo(PVarbinary.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PVarbinary.INSTANCE, sortOrder, maxLength, scale,
+ PVarbinary.INSTANCE);
}
- return true;
- }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] charArr = (Object[]) pArr.array;
+ for (Object i : charArr) {
+ if (!super.isCoercibleTo(PVarbinary.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PVarbinary.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PVarbinary.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarcharArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarcharArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarcharArray.java
index 72561b3..6edaf80 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarcharArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PVarcharArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PVarcharArray extends PArrayDataType<String> {
- public static final PVarcharArray INSTANCE = new PVarcharArray();
-
- private PVarcharArray() {
- super("VARCHAR ARRAY", PDataType.ARRAY_TYPE_BASE + PVarchar.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 26);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PVarcharArray INSTANCE = new PVarcharArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PVarcharArray() {
+ super("VARCHAR ARRAY", PDataType.ARRAY_TYPE_BASE + PVarchar.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 26);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PVarchar.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PVarchar.INSTANCE, sortOrder, maxLength, scale,
- PVarchar.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PVarchar.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] charArr = (Object[]) pArr.array;
- for (Object i : charArr) {
- if (!super.isCoercibleTo(PVarchar.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PVarchar.INSTANCE, sortOrder, maxLength, scale,
+ PVarchar.INSTANCE);
}
- return true;
- }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] charArr = (Object[]) pArr.array;
+ for (Object i : charArr) {
+ if (!super.isCoercibleTo(PVarchar.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PVarchar.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PVarchar.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java
index 1e3516d..64d064a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java
@@ -32,8 +32,8 @@ import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.WritableUtils;
import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
import org.apache.phoenix.query.KeyRange;
-import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PDataType;
import com.google.common.base.Preconditions;
@@ -285,14 +285,16 @@ public class ByteUtil {
totalLength += writable.getLength();
}
byte[] result = new byte[totalLength];
- int offset = 0;
+ int totalOffset = 0;
for (ImmutableBytesWritable array : writables) {
byte[] bytes = array.get();
+ int offset = array.getOffset();
if (sortOrder == SortOrder.DESC) {
- bytes = SortOrder.invert(bytes, array.getOffset(), new byte[array.getLength()], 0, array.getLength());
+ bytes = SortOrder.invert(bytes, offset, new byte[array.getLength()], 0, array.getLength());
+ offset = 0;
}
- System.arraycopy(bytes, array.getOffset(), result, offset, array.getLength());
- offset += array.getLength();
+ System.arraycopy(bytes, offset, result, totalOffset, array.getLength());
+ totalOffset += array.getLength();
}
return result;
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
index 91fd2cb..fbc15be 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
@@ -185,7 +185,7 @@ public class MetaDataUtil {
}
public static PTableType getTableType(List<Mutation> tableMetaData, KeyValueBuilder builder,
- ImmutableBytesPtr value) {
+ ImmutableBytesWritable value) {
if (getMutationValue(getPutOnlyTableHeaderRow(tableMetaData),
PhoenixDatabaseMetaData.TABLE_TYPE_BYTES, builder, value)) {
return PTableType.fromSerializedValue(value.get()[value.getOffset()]);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/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 92bb1d8..61642bc 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
@@ -67,6 +67,7 @@ import org.apache.phoenix.jdbc.PhoenixResultSet;
import org.apache.phoenix.monitoring.GlobalClientMetrics;
import org.apache.phoenix.monitoring.GlobalMetric;
import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.schema.AmbiguousColumnException;
import org.apache.phoenix.schema.ColumnNotFoundException;
import org.apache.phoenix.schema.KeyValueSchema;
@@ -78,12 +79,14 @@ import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.PTable.IndexType;
import org.apache.phoenix.schema.PTableKey;
import org.apache.phoenix.schema.PTableType;
-import org.apache.phoenix.schema.RowKeySchema;
import org.apache.phoenix.schema.RowKeyValueAccessor;
import org.apache.phoenix.schema.TableNotFoundException;
import org.apache.phoenix.schema.ValueBitSet;
import org.apache.phoenix.schema.types.PDataType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -96,6 +99,8 @@ import com.google.common.collect.Lists;
* @since 0.1
*/
public class PhoenixRuntime {
+ private static final Logger logger = LoggerFactory.getLogger(PhoenixRuntime.class);
+
/**
* Use this connection property to control HBase timestamps
* by specifying your own long timestamp value at connection time. All
@@ -191,24 +196,39 @@ public class PhoenixRuntime {
conn = DriverManager.getConnection(jdbcUrl, props)
.unwrap(PhoenixConnection.class);
- for (String inputFile : execCmd.getInputFiles()) {
- if (inputFile.endsWith(SQL_FILE_EXT)) {
- PhoenixRuntime.executeStatements(conn,
- new FileReader(inputFile), Collections.emptyList());
- } else if (inputFile.endsWith(CSV_FILE_EXT)) {
-
- String tableName = execCmd.getTableName();
- if (tableName == null) {
- tableName = SchemaUtil.normalizeIdentifier(
- inputFile.substring(inputFile.lastIndexOf(File.separatorChar) + 1,
- inputFile.length() - CSV_FILE_EXT.length()));
+ if (execCmd.isUpgrade()) {
+ if (execCmd.getInputFiles().isEmpty()) {
+ Set<String> tablesNeedingUpgrade = UpgradeUtil.getPhysicalTablesWithDescVarLengthRowKey(conn);
+ if (tablesNeedingUpgrade.isEmpty()) {
+ String msg = "No tables are required to be upgraded due to incorrect row key order for descending, variable length columsn (PHOENIX-2067)";
+ System.out.println(msg);
+ } else {
+ String msg = "The following tables require upgrade due to a bug causing the row key to be incorrect for descending columns (PHOENIX-2067):\n" + Joiner.on(' ').join(tablesNeedingUpgrade);
+ System.out.println("WARNING: " + msg);
+ }
+ } else {
+ UpgradeUtil.upgradeDescVarLengthRowKeys(conn, execCmd.getInputFiles());
+ }
+ } else {
+ for (String inputFile : execCmd.getInputFiles()) {
+ if (inputFile.endsWith(SQL_FILE_EXT)) {
+ PhoenixRuntime.executeStatements(conn,
+ new FileReader(inputFile), Collections.emptyList());
+ } else if (inputFile.endsWith(CSV_FILE_EXT)) {
+
+ String tableName = execCmd.getTableName();
+ if (tableName == null) {
+ tableName = SchemaUtil.normalizeIdentifier(
+ inputFile.substring(inputFile.lastIndexOf(File.separatorChar) + 1,
+ inputFile.length() - CSV_FILE_EXT.length()));
+ }
+ CSVCommonsLoader csvLoader =
+ new CSVCommonsLoader(conn, tableName, execCmd.getColumns(),
+ execCmd.isStrict(), execCmd.getFieldDelimiter(),
+ execCmd.getQuoteCharacter(), execCmd.getEscapeCharacter(),
+ execCmd.getArrayElementSeparator());
+ csvLoader.upsert(inputFile);
}
- CSVCommonsLoader csvLoader =
- new CSVCommonsLoader(conn, tableName, execCmd.getColumns(),
- execCmd.isStrict(), execCmd.getFieldDelimiter(),
- execCmd.getQuoteCharacter(), execCmd.getEscapeCharacter(),
- execCmd.getArrayElementSeparator());
- csvLoader.upsert(inputFile);
}
}
} catch (Throwable t) {
@@ -459,6 +479,7 @@ public class PhoenixRuntime {
private String arrayElementSeparator;
private boolean strict;
private List<String> inputFiles;
+ private boolean isUpgrade;
/**
* Factory method to build up an {@code ExecutionCommand} based on supplied parameters.
@@ -483,6 +504,11 @@ public class PhoenixRuntime {
"character");
Option arrayValueSeparatorOption = new Option("a", "array-separator", true,
"Define the array element separator, defaults to ':'");
+ Option upgradeOption = new Option("u", "upgrade", false, "Upgrades tables specified as arguments " +
+ "by rewriting them with the correct row key for descending columns. If no arguments are " +
+ "specified, then tables that need to be upgraded will be displayed. " +
+ "Note that " + QueryServices.THREAD_TIMEOUT_MS_ATTRIB + " and hbase.regionserver.lease.period " +
+ "parameters must be set very high to prevent timeouts when upgrading.");
Options options = new Options();
options.addOption(tableOption);
options.addOption(headerOption);
@@ -491,6 +517,7 @@ public class PhoenixRuntime {
options.addOption(quoteCharacterOption);
options.addOption(escapeCharacterOption);
options.addOption(arrayValueSeparatorOption);
+ options.addOption(upgradeOption);
CommandLineParser parser = new PosixParser();
CommandLine cmdLine = null;
@@ -530,6 +557,10 @@ public class PhoenixRuntime {
execCmd.arrayElementSeparator = cmdLine.getOptionValue(
arrayValueSeparatorOption.getOpt(),
CSVCommonsLoader.DEFAULT_ARRAY_ELEMENT_SEPARATOR);
+
+ if (cmdLine.hasOption(upgradeOption.getOpt())) {
+ execCmd.isUpgrade = true;
+ }
List<String> argList = Lists.newArrayList(cmdLine.getArgList());
@@ -539,21 +570,19 @@ public class PhoenixRuntime {
execCmd.connectionString = argList.remove(0);
List<String> inputFiles = Lists.newArrayList();
for (String arg : argList) {
- if (arg.endsWith(CSV_FILE_EXT) || arg.endsWith(SQL_FILE_EXT)) {
+ if (execCmd.isUpgrade || arg.endsWith(CSV_FILE_EXT) || arg.endsWith(SQL_FILE_EXT)) {
inputFiles.add(arg);
} else {
usageError("Don't know how to interpret argument '" + arg + "'", options);
}
}
- if (inputFiles.isEmpty()) {
+ if (inputFiles.isEmpty() && !execCmd.isUpgrade) {
usageError("At least one input file must be supplied", options);
}
execCmd.inputFiles = inputFiles;
-
-
return execCmd;
}
@@ -620,87 +649,12 @@ public class PhoenixRuntime {
public boolean isStrict() {
return strict;
}
- }
-
- /**
- * Encode the primary key values from the table as a byte array. The values must
- * be in the same order as the primary key constraint. If the connection and
- * table are both tenant-specific, the tenant ID column must not be present in
- * the values.
- * @param conn an open connection
- * @param fullTableName the full table name
- * @param values the values of the primary key columns ordered in the same order
- * as the primary key constraint
- * @return the encoded byte array
- * @throws SQLException if the table cannot be found or the incorrect number of
- * of values are provided
- * @see #decodePK(Connection, String, byte[]) to decode the byte[] back to the
- * values
- */
- @Deprecated
- public static byte[] encodePK(Connection conn, String fullTableName, Object[] values) throws SQLException {
- PTable table = getTable(conn, fullTableName);
- PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
- int offset = (table.getBucketNum() == null ? 0 : 1) + (table.isMultiTenant() && pconn.getTenantId() != null ? 1 : 0);
- List<PColumn> pkColumns = table.getPKColumns();
- if (pkColumns.size() - offset != values.length) {
- throw new SQLException("Expected " + (pkColumns.size() - offset) + " but got " + values.length);
- }
- PDataType type = null;
- TrustedByteArrayOutputStream output = new TrustedByteArrayOutputStream(table.getRowKeySchema().getEstimatedValueLength());
- try {
- for (int i = offset; i < pkColumns.size(); i++) {
- if (type != null && !type.isFixedWidth()) {
- output.write(QueryConstants.SEPARATOR_BYTE);
- }
- type = pkColumns.get(i).getDataType();
- //for fixed width data types like CHAR and BINARY, we need to pad values to be of max length.
- Object paddedObj = type.pad(values[i - offset], pkColumns.get(i).getMaxLength());
- byte[] value = type.toBytes(paddedObj);
- output.write(value);
- }
- return output.toByteArray();
- } finally {
- try {
- output.close();
- } catch (IOException e) {
- throw new RuntimeException(e); // Impossible
- }
+ public boolean isUpgrade() {
+ return isUpgrade;
}
}
-
- /**
- * Decode a byte array value back into the Object values of the
- * primary key constraint. If the connection and table are both
- * tenant-specific, the tenant ID column is not expected to have
- * been encoded and will not appear in the returned values.
- * @param conn an open connection
- * @param name the full table name
- * @param encodedValue the value that was encoded with {@link #encodePK(Connection, String, Object[])}
- * @return the Object values encoded in the byte array value
- * @throws SQLException
- */
- @Deprecated
- public static Object[] decodePK(Connection conn, String name, byte[] value) throws SQLException {
- PTable table = getTable(conn, name);
- PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
- int offset = (table.getBucketNum() == null ? 0 : 1) + (table.isMultiTenant() && pconn.getTenantId() != null ? 1 : 0);
- int nValues = table.getPKColumns().size() - offset;
- RowKeySchema schema = table.getRowKeySchema();
- Object[] values = new Object[nValues];
- ImmutableBytesWritable ptr = new ImmutableBytesWritable();
- schema.iterator(value, ptr);
- int i = 0;
- int fieldIdx = offset;
- while (i < nValues && schema.next(ptr, fieldIdx, value.length) != null) {
- values[i] = schema.getField(fieldIdx).getDataType().toObject(ptr);
- i++;
- fieldIdx++;
- }
- return values;
- }
-
+
/**
* Returns the opitmized query plan used by phoenix for executing the sql.
* @param stmt to return the plan for
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
index 3dff972..d63edbb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
@@ -326,13 +326,15 @@ public class ScanUtil {
// but the index for the field it represents in the schema
// should be incremented by 1 + value in the current slotSpan index
// slotSpan stores the number of columns beyond one that the range spans
+ Field field = null;
int i = slotStartIndex, fieldIndex = ScanUtil.getRowKeyPosition(slotSpan, slotStartIndex);
for (i = slotStartIndex; i < slotEndIndex; i++) {
// Build up the key by appending the bound of each key range
// from the current position of each slot.
KeyRange range = slots.get(i).get(position[i]);
// Use last slot in a multi-span column to determine if fixed width
- boolean isFixedWidth = schema.getField(fieldIndex + slotSpan[i]).getDataType().isFixedWidth();
+ field = schema.getField(fieldIndex + slotSpan[i]);
+ boolean isFixedWidth = field.getDataType().isFixedWidth();
fieldIndex += slotSpan[i] + 1;
/*
* If the current slot is unbound then stop if:
@@ -369,9 +371,11 @@ public class ScanUtil {
// key slots would cause the flag to become true.
lastInclusiveUpperSingleKey = range.isSingleKey() && inclusiveUpper;
anyInclusiveUpperRangeKey |= !range.isSingleKey() && inclusiveUpper;
+ // A match for IS NULL or IS NOT NULL should not have a DESC_SEPARATOR_BYTE as nulls sort first
+ byte sepByte = SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), bytes.length == 0 || range == KeyRange.IS_NULL_RANGE || range == KeyRange.IS_NOT_NULL_RANGE, field);
- if (!isFixedWidth && ( fieldIndex < schema.getMaxFields() || inclusiveUpper || exclusiveLower)) {
- key[offset++] = QueryConstants.SEPARATOR_BYTE;
+ if (!isFixedWidth && ( fieldIndex < schema.getMaxFields() || inclusiveUpper || exclusiveLower || sepByte == QueryConstants.DESC_SEPARATOR_BYTE)) {
+ key[offset++] = sepByte;
// Set lastInclusiveUpperSingleKey back to false if this is the last pk column
// as we don't want to increment the null byte in this case
lastInclusiveUpperSingleKey &= i < schema.getMaxFields()-1;
@@ -484,10 +488,11 @@ public class ScanUtil {
while (schema.next(ptr, pos, maxOffset) != null) {
pos++;
}
- if (!schema.getField(pos-1).getDataType().isFixedWidth()) {
+ Field field = schema.getField(pos-1);
+ if (!field.getDataType().isFixedWidth()) {
byte[] newLowerRange = new byte[key.length + 1];
System.arraycopy(key, 0, newLowerRange, 0, key.length);
- newLowerRange[key.length] = QueryConstants.SEPARATOR_BYTE;
+ newLowerRange[key.length] = SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), key.length==0, field);
key = newLowerRange;
} else {
key = Arrays.copyOf(key, key.length);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
index c674140..d01bf39 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
@@ -39,6 +39,7 @@ import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.exception.SQLExceptionInfo;
+import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
@@ -721,4 +722,26 @@ public class SchemaUtil {
fullColumnName = fullColumnName.replaceAll(ESCAPE_CHARACTER, "");
return fullColumnName.trim();
}
+
+ /**
+ * Return the separator byte to use based on:
+ * @param rowKeyOrderOptimizable whether or not the table may optimize descending row keys. If the
+ * table has no descending row keys, this will be true. Also, if the table has been upgraded (using
+ * a new -u option for psql.py), then it'll be true
+ * @param isNullValue whether or not the value is null. We use a null byte still if the value is null
+ * regardless of sort order since nulls will always sort first this way.
+ * @param sortOrder whether the value sorts ascending or descending.
+ * @return the byte to use as the separator
+ */
+ public static byte getSeparatorByte(boolean rowKeyOrderOptimizable, boolean isNullValue, SortOrder sortOrder) {
+ return !rowKeyOrderOptimizable || isNullValue || sortOrder == SortOrder.ASC ? QueryConstants.SEPARATOR_BYTE : QueryConstants.DESC_SEPARATOR_BYTE;
+ }
+
+ public static byte getSeparatorByte(boolean rowKeyOrderOptimizable, boolean isNullValue, Field f) {
+ return getSeparatorByte(rowKeyOrderOptimizable, isNullValue, f.getSortOrder());
+ }
+
+ public static byte getSeparatorByte(boolean rowKeyOrderOptimizable, boolean isNullValue, Expression e) {
+ return getSeparatorByte(rowKeyOrderOptimizable, isNullValue, e.getSortOrder());
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/util/TupleUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/TupleUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/TupleUtil.java
index 1a1b2c9..f495a7e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/TupleUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/TupleUtil.java
@@ -113,10 +113,9 @@ public class TupleUtil {
}
for (int i = 1; i < expressions.size(); i++) {
if (!expression.getDataType().isFixedWidth()) {
- output.write(QueryConstants.SEPARATOR_BYTE);
+ output.write(SchemaUtil.getSeparatorByte(true, value.getLength()==0, expression));
}
expression = expressions.get(i);
- // TODO: should we track trailing null values and omit the separator bytes?
if (expression.evaluate(result, value)) {
output.write(value.get(), value.getOffset(), value.getLength());
} else if (i < expressions.size()-1 && expression.getDataType().isFixedWidth()) {
@@ -125,6 +124,10 @@ public class TupleUtil {
throw new DoNotRetryIOException("Non terminating null value found for fixed width expression (" + expression + ") in row: " + result);
}
}
+ // Write trailing separator if last expression was variable length and descending
+ if (!expression.getDataType().isFixedWidth() && SchemaUtil.getSeparatorByte(true, value.getLength()==0, expression) == QueryConstants.DESC_SEPARATOR_BYTE) {
+ output.write(QueryConstants.DESC_SEPARATOR_BYTE);
+ }
byte[] outputBytes = output.getBuffer();
value.set(outputBytes, 0, output.size());
return value;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
index c829799..e59ea98 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
@@ -35,19 +35,25 @@ import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COU
import static org.apache.phoenix.query.QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT;
import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.TableName;
@@ -60,6 +66,7 @@ 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.coprocessor.MetaDataEndpointImpl;
import org.apache.phoenix.coprocessor.MetaDataProtocol;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
@@ -67,15 +74,24 @@ import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PNameFactory;
import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTable.IndexType;
import org.apache.phoenix.schema.PTable.LinkType;
+import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.SaltingUtil;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PBoolean;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDecimalArray;
import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PLong;
+import org.apache.phoenix.schema.types.PVarchar;
+import org.apache.phoenix.schema.types.PVarcharArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
public class UpgradeUtil {
private static final Logger logger = LoggerFactory.getLogger(UpgradeUtil.class);
@@ -808,4 +824,289 @@ public class UpgradeUtil {
}
}
+ private static String getTableRVC(List<String> tableNames) {
+ StringBuilder query = new StringBuilder("(");
+ for (int i = 0; i < tableNames.size(); i+=3) {
+ String tenantId = tableNames.get(i);
+ String schemaName = tableNames.get(i+1);
+ String tableName = tableNames.get(i+2);
+ query.append('(');
+ query.append(tenantId == null ? "null" : ("'" + tenantId + "'"));
+ query.append(',');
+ query.append(schemaName == null ? "null" : ("'" + schemaName + "'"));
+ query.append(',');
+ query.append("'" + tableName + "'");
+ query.append("),");
+ }
+ // Replace trailing , with ) to end IN expression
+ query.setCharAt(query.length()-1, ')');
+ return query.toString();
+ }
+
+ private static List<String> addPhysicalTables(PhoenixConnection conn, ResultSet rs, PTableType otherType, Set<String> physicalTables) throws SQLException {
+ List<String> tableNames = Lists.newArrayListWithExpectedSize(1024);
+ while (rs.next()) {
+ tableNames.add(rs.getString(1));
+ tableNames.add(rs.getString(2));
+ tableNames.add(rs.getString(3));
+ }
+ if (tableNames.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ List<String> otherTables = Lists.newArrayListWithExpectedSize(tableNames.size());
+ // Find the header rows for tables that have not been upgraded already.
+ // We don't care about views, as the row key cannot be different than the table.
+ // We need this query to find physical tables which won't have a link row.
+ String query = "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME,TABLE_TYPE\n" +
+ "FROM SYSTEM.CATALOG (ROW_KEY_ORDER_OPTIMIZABLE BOOLEAN)\n" +
+ "WHERE COLUMN_NAME IS NULL\n" +
+ "AND COLUMN_FAMILY IS NULL\n" +
+ "AND ROW_KEY_ORDER_OPTIMIZABLE IS NULL\n" +
+ "AND TABLE_TYPE IN ('" + PTableType.TABLE.getSerializedValue() + "','" + otherType.getSerializedValue() + "')\n" +
+ "AND (TENANT_ID, TABLE_SCHEM, TABLE_NAME) IN " + getTableRVC(tableNames);
+ rs = conn.createStatement().executeQuery(query);
+
+ while (rs.next()) {
+ if (PTableType.TABLE.getSerializedValue().equals(rs.getString(4))) {
+ physicalTables.add(SchemaUtil.getTableName(rs.getString(2), rs.getString(3)));
+ } else {
+ otherTables.add(rs.getString(1));
+ otherTables.add(rs.getString(2));
+ otherTables.add(rs.getString(3));
+ }
+ }
+ return otherTables;
+ }
+ /**
+ * Identify the tables that need to be upgraded due to PHOENIX-2067
+ */
+ public static Set<String> getPhysicalTablesWithDescVarLengthRowKey(PhoenixConnection conn) throws SQLException {
+ // First query finds column rows of tables that need to be upgraded.
+ // We cannot tell if the column is from a table, view, or index however.
+ ResultSet rs = conn.createStatement().executeQuery(
+ "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" +
+ "FROM SYSTEM.CATALOG cat1\n" +
+ "WHERE COLUMN_NAME IS NOT NULL\n" +
+ "AND COLUMN_FAMILY IS NULL\n" +
+ "AND SORT_ORDER = " + SortOrder.DESC.getSystemValue() + "\n" +
+ "AND DATA_TYPE IN (" + PVarchar.INSTANCE.getSqlType() + "," + PDecimal.INSTANCE.getSqlType() + "," + PVarcharArray.INSTANCE.getSqlType() + "," + PDecimalArray.INSTANCE.getSqlType() + ")\n" +
+ "GROUP BY TENANT_ID,TABLE_SCHEM,TABLE_NAME");
+ Set<String> physicalTables = Sets.newHashSetWithExpectedSize(1024);
+ List<String> remainingTableNames = addPhysicalTables(conn, rs, PTableType.INDEX, physicalTables);
+ if (!remainingTableNames.isEmpty()) {
+ // Find tables/views for index
+ String indexLinkQuery = "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" +
+ "FROM SYSTEM.CATALOG\n" +
+ "WHERE COLUMN_NAME IS NULL\n" +
+ "AND (TENANT_ID, TABLE_SCHEM, COLUMN_FAMILY) IN " + getTableRVC(remainingTableNames) + "\n" +
+ "AND LINK_TYPE = " + LinkType.INDEX_TABLE.getSerializedValue();
+ rs = conn.createStatement().executeQuery(indexLinkQuery);
+ remainingTableNames = addPhysicalTables(conn, rs, PTableType.VIEW, physicalTables);
+ if (!remainingTableNames.isEmpty()) {
+ // Find physical table name from views, splitting on '.' to get schema name and table name
+ String physicalLinkQuery = "SELECT null, " +
+ " CASE WHEN INSTR(COLUMN_FAMILY,'.') = 0 THEN NULL ELSE SUBSTR(COLUMN_FAMILY,1,INSTR(COLUMN_FAMILY,'.')) END,\n" +
+ " CASE WHEN INSTR(COLUMN_FAMILY,'.') = 0 THEN COLUMN_FAMILY ELSE SUBSTR(COLUMN_FAMILY,INSTR(COLUMN_FAMILY,'.')+1) END\n" +
+ "FROM SYSTEM.CATALOG\n" +
+ "WHERE COLUMN_NAME IS NULL\n" +
+ "AND COLUMN_FAMILY IS NOT NULL\n" +
+ "AND (TENANT_ID, TABLE_SCHEM, TABLE_NAME) IN " + getTableRVC(remainingTableNames) + "\n" +
+ "AND LINK_TYPE = " + LinkType.PHYSICAL_TABLE.getSerializedValue();
+ rs = conn.createStatement().executeQuery(physicalLinkQuery);
+ // Add any tables (which will all be physical tables) which have not already been upgraded.
+ addPhysicalTables(conn, rs, PTableType.TABLE, physicalTables);
+ }
+ }
+ return physicalTables;
+ }
+
+ private static void upgradeDescVarLengthRowKeys(PhoenixConnection upgradeConn, PhoenixConnection globalConn, String schemaName, String tableName, boolean isTable) throws SQLException {
+ String escapedTableName = SchemaUtil.getEscapedTableName(schemaName, tableName);
+ String tenantInfo = "";
+ PName tenantId = PName.EMPTY_NAME;
+ if (upgradeConn.getTenantId() != null) {
+ tenantId = upgradeConn.getTenantId();
+ tenantInfo = " for tenant " + tenantId.getString();
+ }
+ String msg = "Starting upgrade of " + escapedTableName + tenantInfo + "...";
+ System.out.println(msg);
+ logger.info(msg);
+ ResultSet rs = upgradeConn.createStatement().executeQuery("SELECT /*+ NO_INDEX */ count(*) FROM " + escapedTableName);
+ rs.next(); // Run query
+ List<String> tableNames = Lists.newArrayListWithExpectedSize(1024);
+ tableNames.add(tenantId == PName.EMPTY_NAME ? null : tenantId.getString());
+ tableNames.add(schemaName);
+ tableNames.add(tableName);
+ // Find views to mark as upgraded
+ if (isTable) {
+ String physicalName = SchemaUtil.getTableName(schemaName, tableName);
+ String query =
+ "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" +
+ "FROM SYSTEM.CATALOG\n" +
+ "WHERE COLUMN_NAME IS NULL\n" +
+ "AND COLUMN_FAMILY = '" + physicalName + "'" +
+ "AND LINK_TYPE = " + LinkType.PHYSICAL_TABLE.getSerializedValue();
+ rs = globalConn.createStatement().executeQuery(query);
+ while (rs.next()) {
+ tableNames.add(rs.getString(1));
+ tableNames.add(rs.getString(2));
+ tableNames.add(rs.getString(3));
+ }
+ }
+ // Mark the table and views as upgraded now
+ for (int i = 0; i < tableNames.size(); i += 3) {
+ String theTenantId = tableNames.get(i);
+ String theSchemaName = tableNames.get(i+1);
+ String theTableName = tableNames.get(i+2);
+ globalConn.createStatement().execute("UPSERT INTO " + PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME +
+ " (" + PhoenixDatabaseMetaData.TENANT_ID + "," +
+ PhoenixDatabaseMetaData.TABLE_SCHEM + "," +
+ PhoenixDatabaseMetaData.TABLE_NAME + "," +
+ MetaDataEndpointImpl.ROW_KEY_ORDER_OPTIMIZABLE + " BOOLEAN"
+ + ") VALUES (" +
+ "'" + (theTenantId == null ? StringUtil.EMPTY_STRING : theTenantId) + "'," +
+ "'" + (theSchemaName == null ? StringUtil.EMPTY_STRING : theSchemaName) + "'," +
+ "'" + theTableName + "'," +
+ "TRUE)");
+ }
+ globalConn.commit();
+ for (int i = 0; i < tableNames.size(); i += 3) {
+ String theTenantId = tableNames.get(i);
+ String theSchemaName = tableNames.get(i+1);
+ String theTableName = tableNames.get(i+2);
+ globalConn.getQueryServices().clearTableFromCache(
+ theTenantId == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(theTenantId),
+ theSchemaName == null ? ByteUtil.EMPTY_BYTE_ARRAY : Bytes.toBytes(schemaName),
+ Bytes.toBytes(theTableName), HConstants.LATEST_TIMESTAMP);
+ }
+ msg = "Completed upgrade of " + escapedTableName + tenantInfo;
+ System.out.println(msg);
+ logger.info(msg);
+ }
+
+ private static boolean isInvalidTableToUpgrade(PTable table) throws SQLException {
+ return (table.getType() != PTableType.TABLE || // Must be a table
+ table.getTenantId() != null || // Must be global
+ !table.getPhysicalName().equals(table.getName())); // Must be the physical table
+ }
+ /**
+ * Upgrade tables and their indexes due to a bug causing descending row keys to have a row key that
+ * prevents them from being sorted correctly (PHOENIX-2067).
+ */
+ public static void upgradeDescVarLengthRowKeys(PhoenixConnection conn, List<String> tablesToUpgrade) throws SQLException {
+ if (tablesToUpgrade.isEmpty()) {
+ return;
+ }
+ if (conn.getClientInfo(PhoenixRuntime.CURRENT_SCN_ATTRIB) != null) {
+ throw new SQLException("May not specify the CURRENT_SCN property when upgrading");
+ }
+ if (conn.getClientInfo(PhoenixRuntime.TENANT_ID_ATTRIB) != null) {
+ throw new SQLException("May not specify the TENANT_ID_ATTRIB property when upgrading");
+ }
+ List<PTable> tablesNeedingUpgrading = Lists.newArrayListWithExpectedSize(tablesToUpgrade.size());
+ List<String> invalidTables = Lists.newArrayListWithExpectedSize(tablesToUpgrade.size());
+ for (String fullTableName : tablesToUpgrade) {
+ PTable table = PhoenixRuntime.getTable(conn, fullTableName);
+ if (isInvalidTableToUpgrade(table)) {
+ invalidTables.add(fullTableName);
+ } else {
+ tablesNeedingUpgrading.add(table);
+ }
+ }
+ if (!invalidTables.isEmpty()) {
+ StringBuilder buf = new StringBuilder("Only physical tables should be upgraded as their views and indexes will be updated with them: ");
+ for (String fullTableName : invalidTables) {
+ buf.append(fullTableName);
+ buf.append(' ');
+ }
+ throw new SQLException(buf.toString());
+ }
+ PhoenixConnection upgradeConn = new PhoenixConnection(conn, true);
+ try {
+ upgradeConn.setAutoCommit(true);
+ for (PTable table : tablesNeedingUpgrading) {
+ boolean wasUpgraded = false;
+ if (!table.rowKeyOrderOptimizable()) {
+ wasUpgraded = true;
+ upgradeDescVarLengthRowKeys(upgradeConn, conn, table.getSchemaName().getString(), table.getTableName().getString(), true);
+ }
+
+ // Upgrade global indexes
+ for (PTable index : table.getIndexes()) {
+ if (!index.rowKeyOrderOptimizable() && index.getIndexType() != IndexType.LOCAL) {
+ wasUpgraded = true;
+ upgradeDescVarLengthRowKeys(upgradeConn, conn, index.getSchemaName().getString(), index.getTableName().getString(), false);
+ }
+ }
+
+ String sharedViewIndexName = Bytes.toString(MetaDataUtil.getViewIndexPhysicalName(table.getName().getBytes()));
+ // Upgrade view indexes
+ wasUpgraded |= upgradeSharedIndex(upgradeConn, conn, sharedViewIndexName);
+ String sharedLocalIndexName = Bytes.toString(MetaDataUtil.getLocalIndexPhysicalName(table.getName().getBytes()));
+ // Upgrade view indexes
+ wasUpgraded |= upgradeSharedIndex(upgradeConn, conn, sharedLocalIndexName);
+
+ if (!wasUpgraded) {
+ System.out.println("Upgrade not required for this table or its indexes: " + table.getName().getString());
+ }
+ }
+ } finally {
+ upgradeConn.close();
+ }
+ }
+
+ /**
+ * Upgrade shared indexes by querying for all that are associated with our
+ * physical table.
+ * @return true if any upgrades were performed and false otherwise.
+ */
+ private static boolean upgradeSharedIndex(PhoenixConnection upgradeConn, PhoenixConnection globalConn, String physicalName) throws SQLException {
+ String query =
+ "SELECT TENANT_ID,TABLE_SCHEM,TABLE_NAME\n" +
+ "FROM SYSTEM.CATALOG cat1\n" +
+ "WHERE COLUMN_NAME IS NULL\n" +
+ "AND COLUMN_FAMILY = '" + physicalName + "'\n" +
+ "AND LINK_TYPE = " + LinkType.PHYSICAL_TABLE.getSerializedValue() + "\n" +
+ "ORDER BY TENANT_ID";
+ ResultSet rs = globalConn.createStatement().executeQuery(query);
+ String lastTenantId = null;
+ Connection conn = globalConn;
+ String url = globalConn.getURL();
+ boolean wasUpgraded = false;
+ while (rs.next()) {
+ String fullTableName = SchemaUtil.getTableName(
+ rs.getString(PhoenixDatabaseMetaData.TABLE_SCHEM),
+ rs.getString(PhoenixDatabaseMetaData.TABLE_NAME));
+ String tenantId = rs.getString(1);
+ if (tenantId != null && !tenantId.equals(lastTenantId)) {
+ if (lastTenantId != null) {
+ conn.close();
+ }
+ // Open tenant-specific connection when we find a new one
+ Properties props = new Properties(globalConn.getClientInfo());
+ props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
+ conn = DriverManager.getConnection(url, props);
+ lastTenantId = tenantId;
+ }
+ PTable table = PhoenixRuntime.getTable(conn, fullTableName);
+ String tableTenantId = table.getTenantId() == null ? null : table.getTenantId().getString();
+ if (Objects.equal(lastTenantId, tableTenantId) && !table.rowKeyOrderOptimizable()) {
+ upgradeDescVarLengthRowKeys(upgradeConn, globalConn, table.getSchemaName().getString(), table.getTableName().getString(), false);
+ wasUpgraded = true;
+ }
+ }
+ rs.close();
+ if (lastTenantId != null) {
+ conn.close();
+ }
+ return wasUpgraded;
+ }
+
+ public static void addRowKeyOrderOptimizableCell(List<Mutation> tableMetadata, byte[] tableHeaderRowKey, long clientTimeStamp) {
+ Put put = new Put(tableHeaderRowKey, clientTimeStamp);
+ put.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+ MetaDataEndpointImpl.ROW_KEY_ORDER_OPTIMIZABLE_BYTES, PBoolean.INSTANCE.toBytes(true));
+ tableMetadata.add(put);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/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 6e637b7..0f34582 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
@@ -1558,6 +1558,31 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
}
@Test
+ public void testDescVarbinaryNotSupported() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute("CREATE TABLE t (k VARBINARY PRIMARY KEY DESC)");
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.DESC_VARBINARY_NOT_SUPPORTED.getErrorCode(), e.getErrorCode());
+ }
+ try {
+ conn.createStatement().execute("CREATE TABLE t (k1 VARCHAR NOT NULL, k2 VARBINARY, CONSTRAINT pk PRIMARY KEY (k1,k2 DESC))");
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.DESC_VARBINARY_NOT_SUPPORTED.getErrorCode(), e.getErrorCode());
+ }
+ try {
+ conn.createStatement().execute("CREATE TABLE t (k1 VARCHAR PRIMARY KEY)");
+ conn.createStatement().execute("ALTER TABLE t ADD k2 VARBINARY PRIMARY KEY DESC");
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.DESC_VARBINARY_NOT_SUPPORTED.getErrorCode(), e.getErrorCode());
+ }
+ conn.close();
+ }
+
+ @Test
public void testDivideByZeroExpressionIndex() throws Exception {
String ddl = "CREATE TABLE t (k1 INTEGER PRIMARY KEY)";
Connection conn = DriverManager.getConnection(getUrl());
@@ -1705,9 +1730,10 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
@Test
public void testOrderByOrderPreservingFwd() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
- conn.createStatement().execute("CREATE TABLE t (k1 date not null, k2 date not null, k3 date not null, v varchar, constraint pk primary key(k1,k2,k3))");
+ conn.createStatement().execute("CREATE TABLE t (k1 date not null, k2 date not null, k3 varchar, v varchar, constraint pk primary key(k1,k2,k3))");
String[] queries = {
"SELECT * FROM T ORDER BY (k1,k2), k3",
+ "SELECT * FROM T ORDER BY k1,k2,k3 NULLS FIRST",
"SELECT * FROM T ORDER BY k1,k2,k3",
"SELECT * FROM T ORDER BY k1,k2",
"SELECT * FROM T ORDER BY k1",
@@ -1727,8 +1753,9 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
@Test
public void testOrderByOrderPreservingRev() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
- conn.createStatement().execute("CREATE TABLE t (k1 date not null, k2 date not null, k3 date not null, v varchar, constraint pk primary key(k1,k2 DESC,k3))");
+ conn.createStatement().execute("CREATE TABLE t (k1 date not null, k2 date not null, k3 varchar, v varchar, constraint pk primary key(k1,k2 DESC,k3 DESC))");
String[] queries = {
+ "SELECT * FROM T ORDER BY INVERT(k1),k2,k3 nulls last",
"SELECT * FROM T ORDER BY INVERT(k1),k2",
"SELECT * FROM T ORDER BY INVERT(k1)",
"SELECT * FROM T ORDER BY TRUNC(k1, 'DAY') DESC, CEIL(k2, 'HOUR') DESC",
@@ -1745,8 +1772,10 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
@Test
public void testNotOrderByOrderPreserving() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
- conn.createStatement().execute("CREATE TABLE t (k1 date not null, k2 date not null, k3 date not null, v varchar, constraint pk primary key(k1,k2,k3))");
+ conn.createStatement().execute("CREATE TABLE t (k1 date not null, k2 varchar, k3 varchar, v varchar, constraint pk primary key(k1,k2,k3 desc))");
String[] queries = {
+ "SELECT * FROM T ORDER BY k1,k2 NULLS LAST",
+ "SELECT * FROM T ORDER BY k1,k2, k3 NULLS LAST",
"SELECT * FROM T ORDER BY k1,k3",
"SELECT * FROM T ORDER BY SUBSTR(TO_CHAR(k1),1,4)",
"SELECT * FROM T ORDER BY k2",
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/test/java/org/apache/phoenix/query/OrderByTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/OrderByTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/OrderByTest.java
new file mode 100644
index 0000000..f270d9d
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/OrderByTest.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.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.Pair;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.junit.Test;
+
+public class OrderByTest extends BaseConnectionlessQueryTest {
+ @Test
+ public void testSortOrderForSingleDescVarLengthCol() throws SQLException {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE t (k VARCHAR PRIMARY KEY DESC)");
+ conn.createStatement().execute("UPSERT INTO t VALUES ('a')");
+ conn.createStatement().execute("UPSERT INTO t VALUES ('ab')");
+
+ Iterator<Pair<byte[],List<KeyValue>>> dataIterator = PhoenixRuntime.getUncommittedDataIterator(conn);
+ List<KeyValue> kvs = dataIterator.next().getSecond();
+ Collections.sort(kvs, KeyValue.COMPARATOR);
+ KeyValue first = kvs.get(0);
+ assertEquals("ab", Bytes.toString(SortOrder.invert(first.getRowArray(), first.getRowOffset(), first.getRowLength()-1)));
+ KeyValue second = kvs.get(1);
+ assertEquals("a", Bytes.toString(SortOrder.invert(second.getRowArray(), second.getRowOffset(), second.getRowLength()-1)));
+ }
+
+ @Test
+ public void testSortOrderForLeadingDescVarLengthColWithNullFollowing() throws SQLException {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE t (k1 VARCHAR, k2 VARCHAR, CONSTRAINT pk PRIMARY KEY (k1 DESC,k2))");
+ conn.createStatement().execute("UPSERT INTO t VALUES ('a')");
+ conn.createStatement().execute("UPSERT INTO t VALUES ('ab')");
+
+ Iterator<Pair<byte[],List<KeyValue>>> dataIterator = PhoenixRuntime.getUncommittedDataIterator(conn);
+ List<KeyValue> kvs = dataIterator.next().getSecond();
+ Collections.sort(kvs, KeyValue.COMPARATOR);
+ KeyValue first = kvs.get(0);
+ assertEquals("ab", Bytes.toString(SortOrder.invert(first.getRowArray(), first.getRowOffset(), first.getRowLength()-1)));
+ KeyValue second = kvs.get(1);
+ assertEquals("a", Bytes.toString(SortOrder.invert(second.getRowArray(), second.getRowOffset(), second.getRowLength()-1)));
+ }
+
+ @Test
+ public void testSortOrderForLeadingDescVarLengthColWithNonNullFollowing() throws SQLException {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE t (k1 VARCHAR, k2 VARCHAR NOT NULL, CONSTRAINT pk PRIMARY KEY (k1 DESC,k2))");
+ conn.createStatement().execute("UPSERT INTO t VALUES ('a','x')");
+ conn.createStatement().execute("UPSERT INTO t VALUES ('ab', 'x')");
+
+ Iterator<Pair<byte[],List<KeyValue>>> dataIterator = PhoenixRuntime.getUncommittedDataIterator(conn);
+ List<KeyValue> kvs = dataIterator.next().getSecond();
+ Collections.sort(kvs, KeyValue.COMPARATOR);
+ KeyValue first = kvs.get(0);
+ assertEquals("ab", Bytes.toString(SortOrder.invert(first.getRowArray(), first.getRowOffset(), 2)));
+ KeyValue second = kvs.get(1);
+ assertEquals("a", Bytes.toString(SortOrder.invert(second.getRowArray(), second.getRowOffset(), 1)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java
index 85f9436..7ab9093 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java
@@ -38,6 +38,7 @@ import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.ConstraintViolationException;
import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.util.TestUtil;
@@ -1754,4 +1755,15 @@ public class PDataTypeTest {
assertTrue(PLong.INSTANCE.compareTo(l, i, PInteger.INSTANCE)==0);
assertTrue(PInteger.INSTANCE.compareTo(i, l, PLong.INSTANCE)==0);
}
+
+ @Test
+ public void testSeparatorBytes() {
+ byte biggest = (byte) 0xFF;
+ assertEquals(biggest, QueryConstants.DESC_SEPARATOR_BYTE);
+ byte[] array = new byte[1];
+ for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+ array[0] = (byte) i;
+ assertTrue(Bytes.compareTo(array, QueryConstants.DESC_SEPARATOR_BYTE_ARRAY) <= 0);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-protocol/src/main/PTable.proto
----------------------------------------------------------------------
diff --git a/phoenix-protocol/src/main/PTable.proto b/phoenix-protocol/src/main/PTable.proto
index cbbbdd6..a327803 100644
--- a/phoenix-protocol/src/main/PTable.proto
+++ b/phoenix-protocol/src/main/PTable.proto
@@ -84,4 +84,5 @@ message PTable {
optional int64 statsTimeStamp = 23;
optional bool storeNulls = 24;
optional int32 baseColumnCount = 25;
+ optional bool rowKeyOrderOptimizable = 26;
}
[16/50] [abbrv] phoenix git commit: PHOENIX-1889 Support
alter/replace and drop functions(Rajeshbabu)
Posted by ma...@apache.org.
PHOENIX-1889 Support alter/replace and drop functions(Rajeshbabu)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/11bdb0ee
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/11bdb0ee
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/11bdb0ee
Branch: refs/heads/calcite
Commit: 11bdb0eedbbea1e58b60fe8ebba21e5c168261b7
Parents: fa2d79a
Author: Rajeshbabu Chintaguntla <ra...@apache.org>
Authored: Thu Jul 9 17:24:39 2015 +0530
Committer: Rajeshbabu Chintaguntla <ra...@apache.org>
Committed: Thu Jul 9 17:24:39 2015 +0530
----------------------------------------------------------------------
.../phoenix/end2end/UserDefinedFunctionsIT.java | 145 ++++++++++++++++++-
phoenix-core/src/main/antlr3/PhoenixSQL.g | 5 +-
.../phoenix/compile/CreateFunctionCompiler.java | 4 +-
.../coprocessor/MetaDataEndpointImpl.java | 40 +++--
.../coprocessor/generated/PFunctionProtos.java | 100 ++++++++++++-
.../apache/phoenix/jdbc/PhoenixStatement.java | 28 ++--
.../phoenix/parse/CreateFunctionStatement.java | 7 +-
.../org/apache/phoenix/parse/PFunction.java | 28 +++-
.../apache/phoenix/parse/ParseNodeFactory.java | 4 +-
.../query/ConnectionQueryServicesImpl.java | 1 +
.../apache/phoenix/schema/MetaDataClient.java | 20 ++-
phoenix-protocol/src/main/PFunction.proto | 1 +
12 files changed, 336 insertions(+), 47 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java
index 613231d..e2b7b4c 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java
@@ -17,15 +17,18 @@
*/
package org.apache.phoenix.end2end;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_FUNCTION_TABLE;
+import static org.apache.phoenix.query.QueryServices.DYNAMIC_JARS_DIR_KEY;
import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL;
import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR;
import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL_TERMINATOR;
import static org.apache.phoenix.util.PhoenixRuntime.PHOENIX_TEST_DRIVER_URL_PARAM;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_FUNCTION_TABLE;
-import static org.apache.phoenix.query.QueryServices.DYNAMIC_JARS_DIR_KEY;
import static org.apache.phoenix.util.TestUtil.LOCALHOST;
-import static org.junit.Assert.*;
+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.io.BufferedInputStream;
import java.io.File;
@@ -34,6 +37,7 @@ import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
+import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashSet;
@@ -60,8 +64,6 @@ import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.schema.FunctionAlreadyExistsException;
import org.apache.phoenix.schema.FunctionNotFoundException;
import org.apache.phoenix.schema.ValueRangeExcpetion;
-import org.apache.phoenix.schema.types.PDataType;
-import org.apache.phoenix.schema.types.PArrayDataType;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.QueryUtil;
import org.apache.phoenix.util.ReadOnlyProps;
@@ -561,6 +563,104 @@ public class UserDefinedFunctionsIT extends BaseOwnClusterIT{
}
@Test
+ public void testUDFsWhenTimestampManagedAtClient() throws Exception {
+ long ts = 100;
+ Properties props = new Properties();
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
+ Connection conn = DriverManager.getConnection(url, props);
+ Statement stmt = conn.createStatement();
+ String query = "select count(*) from "+ SYSTEM_CATALOG_SCHEMA + ".\"" + SYSTEM_FUNCTION_TABLE + "\"";
+ ResultSet rs = stmt.executeQuery(query);
+ rs.next();
+ int numRowsBefore = rs.getInt(1);
+ stmt.execute("create function mysum61(INTEGER, INTEGER CONSTANT defaultValue=10 minvalue=1 maxvalue=15 ) returns INTEGER as 'org.apache.phoenix.end2end."+MY_SUM_CLASS_NAME+"' using jar "
+ + "'"+util.getConfiguration().get(DYNAMIC_JARS_DIR_KEY) + "/myjar2.jar"+"'");
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+ conn = DriverManager.getConnection(url, props);
+ stmt = conn.createStatement();
+ rs = stmt.executeQuery(query);
+ rs.next();
+ int numRowsAfter= rs.getInt(1);
+ assertEquals(3, numRowsAfter - numRowsBefore);
+ stmt.execute("drop function mysum61");
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 20));
+ conn = DriverManager.getConnection(url, props);
+ stmt = conn.createStatement();
+ rs = stmt.executeQuery(query);
+ rs.next();
+ assertEquals(numRowsBefore, rs.getInt(1));
+ conn.createStatement().execute("create table t62(k integer primary key, k1 integer, lastname varchar)");
+ try {
+ rs = stmt.executeQuery("select mysum61(k1) from t62");
+ fail("FunctionNotFoundException should be thrown");
+ } catch(FunctionNotFoundException e) {
+
+ }
+ try {
+ stmt.execute("drop function mysum61");
+ fail("FunctionNotFoundException should be thrown");
+ } catch(FunctionNotFoundException e) {
+
+ }
+ try {
+ stmt.execute("drop function if exists mysum61");
+ } catch(FunctionNotFoundException e) {
+ fail("FunctionNotFoundException should not be thrown");
+ }
+ stmt.execute("create function mysum61(INTEGER, INTEGER CONSTANT defaultValue=10 minvalue=1 maxvalue=15 ) returns INTEGER as 'org.apache.phoenix.end2end."+MY_SUM_CLASS_NAME+"' using jar "
+ + "'"+util.getConfiguration().get(DYNAMIC_JARS_DIR_KEY) + "/myjar2.jar"+"'");
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+ conn = DriverManager.getConnection(url, props);
+ stmt = conn.createStatement();
+ try {
+ rs = stmt.executeQuery("select mysum61(k1) from t62");
+ } catch(FunctionNotFoundException e) {
+ fail("FunctionNotFoundException should not be thrown");
+ }
+ conn.createStatement().execute("create table t61(k integer primary key, k1 integer, lastname varchar)");
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+ conn = DriverManager.getConnection(url, props);
+ stmt = conn.createStatement();
+ stmt.execute("upsert into t61 values(1,1,'jock')");
+ conn.commit();
+ stmt.execute("create function myfunction6(VARCHAR) returns VARCHAR as 'org.apache.phoenix.end2end."+MY_REVERSE_CLASS_NAME+"' using jar "
+ + "'"+util.getConfiguration().get(DYNAMIC_JARS_DIR_KEY) + "/myjar1.jar"+"'");
+ stmt.execute("create or replace function myfunction6(INTEGER, INTEGER CONSTANT defaultValue=10 minvalue=1 maxvalue=15 ) returns INTEGER as 'org.apache.phoenix.end2end."+MY_SUM_CLASS_NAME+"' using jar "
+ + "'"+util.getConfiguration().get(DYNAMIC_JARS_DIR_KEY) + "/myjar2.jar"+"'");
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 50));
+ conn = DriverManager.getConnection(url, props);
+ stmt = conn.createStatement();
+ rs = stmt.executeQuery("select myfunction6(k,12) from t61");
+ assertTrue(rs.next());
+ assertEquals(13, rs.getInt(1));
+ rs = stmt.executeQuery("select myfunction6(k) from t61");
+ assertTrue(rs.next());
+ assertEquals(11, rs.getInt(1));
+ rs = stmt.executeQuery("select k from t61 where myfunction6(k)=11");
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ stmt.execute("create or replace function myfunction6(VARCHAR) returns VARCHAR as 'org.apache.phoenix.end2end."+MY_REVERSE_CLASS_NAME+"' using jar "
+ + "'"+util.getConfiguration().get(DYNAMIC_JARS_DIR_KEY) + "/myjar1.jar"+"'");
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 60));
+ conn = DriverManager.getConnection(url, props);
+ stmt = conn.createStatement();
+ rs = stmt.executeQuery("select k from t61 where myfunction6(lastname)='kcoj'");
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 60));
+ props.setProperty(QueryServices.ALLOW_USER_DEFINED_FUNCTIONS_ATTRIB, "false");
+ conn = DriverManager.getConnection(url, props);
+ stmt = conn.createStatement();
+ try {
+ rs = stmt.executeQuery("select k from t61 where reverse(lastname,11)='kcoj'");
+ fail("FunctionNotFoundException should be thrown.");
+ } catch(FunctionNotFoundException e) {
+
+ }
+
+ }
+
+ @Test
public void testFunctionalIndexesWithUDFFunction() throws Exception {
Connection conn = driver.connect(url, EMPTY_PROPS);
Statement stmt = conn.createStatement();
@@ -591,6 +691,39 @@ public class UserDefinedFunctionsIT extends BaseOwnClusterIT{
assertFalse(rs.next());
}
+ @Test
+ public void testReplaceFunction() throws Exception {
+ Connection conn = driver.connect(url, EMPTY_PROPS);
+ Statement stmt = conn.createStatement();
+ conn.createStatement().execute("create table t10(k integer primary key, k1 integer, lastname varchar)");
+ stmt.execute("upsert into t10 values(1,1,'jock')");
+ conn.commit();
+ stmt.execute("create function myfunction63(VARCHAR) returns VARCHAR as 'org.apache.phoenix.end2end."+MY_REVERSE_CLASS_NAME+"' using jar "
+ + "'"+util.getConfiguration().get(DYNAMIC_JARS_DIR_KEY) + "/myjar1.jar"+"'");
+ stmt.execute("create or replace function myfunction63(INTEGER, INTEGER CONSTANT defaultValue=10 minvalue=1 maxvalue=15 ) returns INTEGER as 'org.apache.phoenix.end2end."+MY_SUM_CLASS_NAME+"' using jar "
+ + "'"+util.getConfiguration().get(DYNAMIC_JARS_DIR_KEY) + "/myjar2.jar"+"'");
+ ResultSet rs = stmt.executeQuery("select myfunction63(k,12) from t10");
+ assertTrue(rs.next());
+ assertEquals(13, rs.getInt(1));
+ rs = stmt.executeQuery("select myfunction63(k) from t10");
+ assertTrue(rs.next());
+ assertEquals(11, rs.getInt(1));
+ rs = stmt.executeQuery("select k from t10 where myfunction63(k)=11");
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ Connection conn2 = driver.connect(url, EMPTY_PROPS);
+ stmt = conn2.createStatement();
+ rs = stmt.executeQuery("select myfunction63(k,12) from t10");
+ assertTrue(rs.next());
+ assertEquals(13, rs.getInt(1));
+ rs = stmt.executeQuery("select myfunction63(k) from t10");
+ assertTrue(rs.next());
+ assertEquals(11, rs.getInt(1));
+ rs = stmt.executeQuery("select k from t10 where myfunction63(k)=11");
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ }
+
/**
* Compiles the test class with bogus code into a .class file.
*/
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/main/antlr3/PhoenixSQL.g
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g
index 69014a2..ca5e778 100644
--- a/phoenix-core/src/main/antlr3/PhoenixSQL.g
+++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g
@@ -122,6 +122,7 @@ tokens
JAR='jar';
DEFAULTVALUE='defaultvalue';
CONSTANT = 'constant';
+ REPLACE = 'replace';
}
@@ -540,12 +541,12 @@ trace_node returns [TraceStatement ret]
// Parse a trace statement.
create_function_node returns [CreateFunctionStatement ret]
- : CREATE (temp=TEMPORARY)? FUNCTION function=identifier
+ : CREATE (OR replace=REPLACE)? (temp=TEMPORARY)? FUNCTION function=identifier
(LPAREN args=zero_or_more_data_types RPAREN)
RETURNS r=identifier AS (className= jar_path)
(USING JAR (jarPath = jar_path))?
{
- $ret = factory.createFunction(new PFunction(SchemaUtil.normalizeIdentifier(function), args,r,(String)className.getValue(), jarPath == null ? null : (String)jarPath.getValue()), temp!=null);;
+ $ret = factory.createFunction(new PFunction(SchemaUtil.normalizeIdentifier(function), args,r,(String)className.getValue(), jarPath == null ? null : (String)jarPath.getValue()), temp!=null, replace!=null);
}
;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateFunctionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateFunctionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateFunctionCompiler.java
index 2e3a873..138c75d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateFunctionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateFunctionCompiler.java
@@ -63,7 +63,9 @@ public class CreateFunctionCompiler {
@Override
public ExplainPlan getExplainPlan() throws SQLException {
- return new ExplainPlan(Collections.singletonList("CREATE FUNCTION"));
+ return new ExplainPlan(Collections.singletonList("CREATE"
+ + (create.getFunctionInfo().isReplace() ? " OR REPLACE" : "")
+ + " FUNCTION"));
}
@Override
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index b27beb4..f786768 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -478,7 +478,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
private List<PFunction> buildFunctions(List<byte[]> keys, Region region,
- long clientTimeStamp) throws IOException, SQLException {
+ long clientTimeStamp, boolean isReplace, List<Mutation> deleteMutationsForReplace) throws IOException, SQLException {
List<KeyRange> keyRanges = Lists.newArrayListWithExpectedSize(keys.size());
for (byte[] key : keys) {
byte[] stopKey = ByteUtil.concat(key, QueryConstants.SEPARATOR_BYTE_ARRAY);
@@ -501,7 +501,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
try {
for(int i = 0; i< keys.size(); i++) {
function = null;
- function = getFunction(scanner);
+ function =
+ getFunction(scanner, isReplace, clientTimeStamp, deleteMutationsForReplace);
if (function == null) {
return null;
}
@@ -828,7 +829,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, stats, baseColumnCount);
}
- private PFunction getFunction(RegionScanner scanner)
+ private PFunction getFunction(RegionScanner scanner, final boolean isReplace, long clientTimeStamp, List<Mutation> deleteMutationsForReplace)
throws IOException, SQLException {
List<Cell> results = Lists.newArrayList();
scanner.next(results);
@@ -837,12 +838,19 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
Cell[] functionKeyValues = new Cell[FUNCTION_KV_COLUMNS.size()];
Cell[] functionArgKeyValues = new Cell[FUNCTION_ARG_KV_COLUMNS.size()];
-
// Create PFunction based on KeyValues from scan
Cell keyValue = results.get(0);
byte[] keyBuffer = keyValue.getRowArray();
int keyLength = keyValue.getRowLength();
int keyOffset = keyValue.getRowOffset();
+ long currentTimeMillis = EnvironmentEdgeManager.currentTimeMillis();
+ if(isReplace) {
+ long deleteTimeStamp =
+ clientTimeStamp == HConstants.LATEST_TIMESTAMP ? currentTimeMillis - 1
+ : (keyValue.getTimestamp() < clientTimeStamp ? clientTimeStamp - 1
+ : keyValue.getTimestamp());
+ deleteMutationsForReplace.add(new Delete(keyBuffer, keyOffset, keyLength, deleteTimeStamp));
+ }
PName tenantId = newPName(keyBuffer, keyOffset, keyLength);
int tenantIdLength = (tenantId == null) ? 0 : tenantId.getBytes().length;
if (tenantIdLength == 0) {
@@ -908,6 +916,14 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
break;
}
Cell typeKv = results.get(0);
+ if(isReplace) {
+ long deleteTimeStamp =
+ clientTimeStamp == HConstants.LATEST_TIMESTAMP ? currentTimeMillis - 1
+ : (typeKv.getTimestamp() < clientTimeStamp ? clientTimeStamp - 1
+ : typeKv.getTimestamp());
+ deleteMutationsForReplace.add(new Delete(typeKv.getRowArray(), typeKv
+ .getRowOffset(), typeKv.getRowLength(), deleteTimeStamp));
+ }
int typeKeyLength = typeKv.getRowLength();
PName typeName =
newPName(typeKv.getRowArray(), typeKv.getRowOffset() + offset, typeKeyLength
@@ -1020,18 +1036,18 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
private PFunction loadFunction(RegionCoprocessorEnvironment env, byte[] key,
- ImmutableBytesPtr cacheKey, long clientTimeStamp, long asOfTimeStamp)
+ ImmutableBytesPtr cacheKey, long clientTimeStamp, long asOfTimeStamp, boolean isReplace, List<Mutation> deleteMutationsForReplace)
throws IOException, SQLException {
Region region = env.getRegion();
Cache<ImmutableBytesPtr,PMetaDataEntity> metaDataCache = GlobalCache.getInstance(this.env).getMetaDataCache();
PFunction function = (PFunction)metaDataCache.getIfPresent(cacheKey);
// We always cache the latest version - fault in if not in cache
- if (function != null) {
+ if (function != null && !isReplace) {
return function;
}
ArrayList<byte[]> arrayList = new ArrayList<byte[]>(1);
arrayList.add(key);
- List<PFunction> functions = buildFunctions(arrayList, region, asOfTimeStamp);
+ List<PFunction> functions = buildFunctions(arrayList, region, asOfTimeStamp, isReplace, deleteMutationsForReplace);
if(functions != null) return functions.get(0);
// if not found then check if newer table already exists and add delete marker for timestamp
// found
@@ -2075,7 +2091,9 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
if(functionsAvailable.size() == numFunctions) return functionsAvailable;
// Query for the latest table first, since it's not cached
- List<PFunction> buildFunctions = buildFunctions(keys, region, clientTimeStamp);
+ List<PFunction> buildFunctions =
+ buildFunctions(keys, region, clientTimeStamp, false,
+ Collections.<Mutation> emptyList());
if(buildFunctions == null || buildFunctions.isEmpty()) {
return null;
}
@@ -2582,7 +2600,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
// exists without making an additional query
ImmutableBytesPtr cacheKey = new FunctionBytesPtr(lockKey);
PFunction function =
- loadFunction(env, lockKey, cacheKey, clientTimeStamp, clientTimeStamp);
+ loadFunction(env, lockKey, cacheKey, clientTimeStamp, clientTimeStamp, request.getReplace(), functionMetaData);
if (function != null) {
if (function.getTimeStamp() < clientTimeStamp) {
// If the function is older than the client time stamp and it's deleted,
@@ -2592,7 +2610,9 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
builder.setMutationTime(EnvironmentEdgeManager.currentTimeMillis());
builder.addFunction(PFunction.toProto(function));
done.run(builder.build());
- return;
+ if(!request.getReplace()) {
+ return;
+ }
}
} else {
builder.setReturnCode(MetaDataProtos.MutationCode.NEWER_FUNCTION_FOUND);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PFunctionProtos.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PFunctionProtos.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PFunctionProtos.java
index 12927aa..7783a95 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PFunctionProtos.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PFunctionProtos.java
@@ -1317,6 +1317,16 @@ public final class PFunctionProtos {
* <code>optional bool isArrayReturnType = 8;</code>
*/
boolean getIsArrayReturnType();
+
+ // optional bool isReplace = 9;
+ /**
+ * <code>optional bool isReplace = 9;</code>
+ */
+ boolean hasIsReplace();
+ /**
+ * <code>optional bool isReplace = 9;</code>
+ */
+ boolean getIsReplace();
}
/**
* Protobuf type {@code PFunction}
@@ -1412,6 +1422,11 @@ public final class PFunctionProtos {
isArrayReturnType_ = input.readBool();
break;
}
+ case 72: {
+ bitField0_ |= 0x00000080;
+ isReplace_ = input.readBool();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -1711,6 +1726,22 @@ public final class PFunctionProtos {
return isArrayReturnType_;
}
+ // optional bool isReplace = 9;
+ public static final int ISREPLACE_FIELD_NUMBER = 9;
+ private boolean isReplace_;
+ /**
+ * <code>optional bool isReplace = 9;</code>
+ */
+ public boolean hasIsReplace() {
+ return ((bitField0_ & 0x00000080) == 0x00000080);
+ }
+ /**
+ * <code>optional bool isReplace = 9;</code>
+ */
+ public boolean getIsReplace() {
+ return isReplace_;
+ }
+
private void initFields() {
functionName_ = "";
arguments_ = java.util.Collections.emptyList();
@@ -1720,6 +1751,7 @@ public final class PFunctionProtos {
tenantId_ = com.google.protobuf.ByteString.EMPTY;
returnType_ = "";
isArrayReturnType_ = false;
+ isReplace_ = false;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -1775,6 +1807,9 @@ public final class PFunctionProtos {
if (((bitField0_ & 0x00000040) == 0x00000040)) {
output.writeBool(8, isArrayReturnType_);
}
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ output.writeBool(9, isReplace_);
+ }
getUnknownFields().writeTo(output);
}
@@ -1816,6 +1851,10 @@ public final class PFunctionProtos {
size += com.google.protobuf.CodedOutputStream
.computeBoolSize(8, isArrayReturnType_);
}
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(9, isReplace_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -1876,6 +1915,11 @@ public final class PFunctionProtos {
result = result && (getIsArrayReturnType()
== other.getIsArrayReturnType());
}
+ result = result && (hasIsReplace() == other.hasIsReplace());
+ if (hasIsReplace()) {
+ result = result && (getIsReplace()
+ == other.getIsReplace());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -1921,6 +1965,10 @@ public final class PFunctionProtos {
hash = (37 * hash) + ISARRAYRETURNTYPE_FIELD_NUMBER;
hash = (53 * hash) + hashBoolean(getIsArrayReturnType());
}
+ if (hasIsReplace()) {
+ hash = (37 * hash) + ISREPLACE_FIELD_NUMBER;
+ hash = (53 * hash) + hashBoolean(getIsReplace());
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -2051,6 +2099,8 @@ public final class PFunctionProtos {
bitField0_ = (bitField0_ & ~0x00000040);
isArrayReturnType_ = false;
bitField0_ = (bitField0_ & ~0x00000080);
+ isReplace_ = false;
+ bitField0_ = (bitField0_ & ~0x00000100);
return this;
}
@@ -2116,6 +2166,10 @@ public final class PFunctionProtos {
to_bitField0_ |= 0x00000040;
}
result.isArrayReturnType_ = isArrayReturnType_;
+ if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
+ to_bitField0_ |= 0x00000080;
+ }
+ result.isReplace_ = isReplace_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -2187,6 +2241,9 @@ public final class PFunctionProtos {
if (other.hasIsArrayReturnType()) {
setIsArrayReturnType(other.getIsArrayReturnType());
}
+ if (other.hasIsReplace()) {
+ setIsReplace(other.getIsReplace());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -2870,6 +2927,39 @@ public final class PFunctionProtos {
return this;
}
+ // optional bool isReplace = 9;
+ private boolean isReplace_ ;
+ /**
+ * <code>optional bool isReplace = 9;</code>
+ */
+ public boolean hasIsReplace() {
+ return ((bitField0_ & 0x00000100) == 0x00000100);
+ }
+ /**
+ * <code>optional bool isReplace = 9;</code>
+ */
+ public boolean getIsReplace() {
+ return isReplace_;
+ }
+ /**
+ * <code>optional bool isReplace = 9;</code>
+ */
+ public Builder setIsReplace(boolean value) {
+ bitField0_ |= 0x00000100;
+ isReplace_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bool isReplace = 9;</code>
+ */
+ public Builder clearIsReplace() {
+ bitField0_ = (bitField0_ & ~0x00000100);
+ isReplace_ = false;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:PFunction)
}
@@ -2903,14 +2993,14 @@ public final class PFunctionProtos {
"\n\017PFunction.proto\"\207\001\n\014PFunctionArg\022\024\n\014ar" +
"gumentType\030\001 \002(\t\022\023\n\013isArrayType\030\002 \001(\010\022\022\n" +
"\nisConstant\030\003 \001(\010\022\024\n\014defaultValue\030\004 \001(\t\022" +
- "\020\n\010minValue\030\005 \001(\t\022\020\n\010maxValue\030\006 \001(\t\"\273\001\n\t" +
+ "\020\n\010minValue\030\005 \001(\t\022\020\n\010maxValue\030\006 \001(\t\"\316\001\n\t" +
"PFunction\022\024\n\014functionName\030\001 \002(\t\022 \n\targum" +
"ents\030\002 \003(\0132\r.PFunctionArg\022\021\n\tclassname\030\003" +
" \002(\t\022\021\n\ttimeStamp\030\004 \002(\003\022\017\n\007jarPath\030\005 \001(\t" +
"\022\020\n\010tenantId\030\006 \001(\014\022\022\n\nreturnType\030\007 \001(\t\022\031" +
- "\n\021isArrayReturnType\030\010 \001(\010BC\n(org.apache." +
- "phoenix.coprocessor.generatedB\017PFunction",
- "ProtosH\001\210\001\001\240\001\001"
+ "\n\021isArrayReturnType\030\010 \001(\010\022\021\n\tisReplace\030\t" +
+ " \001(\010BC\n(org.apache.phoenix.coprocessor.g",
+ "eneratedB\017PFunctionProtosH\001\210\001\001\240\001\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -2928,7 +3018,7 @@ public final class PFunctionProtos {
internal_static_PFunction_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_PFunction_descriptor,
- new java.lang.String[] { "FunctionName", "Arguments", "Classname", "TimeStamp", "JarPath", "TenantId", "ReturnType", "IsArrayReturnType", });
+ new java.lang.String[] { "FunctionName", "Arguments", "Classname", "TimeStamp", "JarPath", "TenantId", "ReturnType", "IsArrayReturnType", "IsReplace", });
return null;
}
};
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
index 2bb3b92..f323ec4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
@@ -116,6 +116,7 @@ import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.query.QueryServicesOptions;
import org.apache.phoenix.schema.ExecuteQueryNotApplicableException;
import org.apache.phoenix.schema.ExecuteUpdateNotApplicableException;
+import org.apache.phoenix.schema.FunctionNotFoundException;
import org.apache.phoenix.schema.MetaDataClient;
import org.apache.phoenix.schema.PDatum;
import org.apache.phoenix.schema.PIndexState;
@@ -354,7 +355,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
@Override
public QueryPlan compilePlan(PhoenixStatement stmt, Sequence.ValueOp seqAction) throws SQLException {
if(!getUdfParseNodes().isEmpty()) {
- stmt.throwIfUnallowedUserDefinedFunctions();
+ stmt.throwIfUnallowedUserDefinedFunctions(getUdfParseNodes());
}
SelectStatement select = SubselectRewriter.flatten(this, stmt.getConnection());
ColumnResolver resolver = FromCompiler.getResolverForQuery(select, stmt.getConnection());
@@ -531,7 +532,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
@Override
public MutationPlan compilePlan(PhoenixStatement stmt, Sequence.ValueOp seqAction) throws SQLException {
if(!getUdfParseNodes().isEmpty()) {
- stmt.throwIfUnallowedUserDefinedFunctions();
+ stmt.throwIfUnallowedUserDefinedFunctions(getUdfParseNodes());
}
UpsertCompiler compiler = new UpsertCompiler(stmt);
MutationPlan plan = compiler.compile(this);
@@ -549,7 +550,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
@Override
public MutationPlan compilePlan(PhoenixStatement stmt, Sequence.ValueOp seqAction) throws SQLException {
if(!getUdfParseNodes().isEmpty()) {
- stmt.throwIfUnallowedUserDefinedFunctions();
+ stmt.throwIfUnallowedUserDefinedFunctions(getUdfParseNodes());
}
DeleteCompiler compiler = new DeleteCompiler(stmt);
MutationPlan plan = compiler.compile(this);
@@ -575,15 +576,15 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
private static class ExecutableCreateFunctionStatement extends CreateFunctionStatement implements CompilableStatement {
- public ExecutableCreateFunctionStatement(PFunction functionInfo, boolean temporary) {
- super(functionInfo, temporary);
+ public ExecutableCreateFunctionStatement(PFunction functionInfo, boolean temporary, boolean isReplace) {
+ super(functionInfo, temporary, isReplace);
}
@SuppressWarnings("unchecked")
@Override
public MutationPlan compilePlan(final PhoenixStatement stmt, Sequence.ValueOp seqAction) throws SQLException {
- stmt.throwIfUnallowedUserDefinedFunctions();
+ stmt.throwIfUnallowedUserDefinedFunctions(Collections.EMPTY_MAP);
CreateFunctionCompiler compiler = new CreateFunctionCompiler(stmt);
return compiler.compile(this);
}
@@ -641,7 +642,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
@Override
public MutationPlan compilePlan(PhoenixStatement stmt, Sequence.ValueOp seqAction) throws SQLException {
if(!getUdfParseNodes().isEmpty()) {
- stmt.throwIfUnallowedUserDefinedFunctions();
+ stmt.throwIfUnallowedUserDefinedFunctions(getUdfParseNodes());
}
CreateIndexCompiler compiler = new CreateIndexCompiler(stmt);
return compiler.compile(this);
@@ -1022,8 +1023,8 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
}
@Override
- public CreateFunctionStatement createFunction(PFunction functionInfo, boolean temporary) {
- return new ExecutableCreateFunctionStatement(functionInfo, temporary);
+ public CreateFunctionStatement createFunction(PFunction functionInfo, boolean temporary, boolean isReplace) {
+ return new ExecutableCreateFunctionStatement(functionInfo, temporary, isReplace);
}
@Override
public DropSequenceStatement dropSequence(TableName tableName, boolean ifExists, int bindCount){
@@ -1504,14 +1505,17 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
this.lastQueryPlan = lastQueryPlan;
}
- private void throwIfUnallowedUserDefinedFunctions() throws SQLException {
+ private void throwIfUnallowedUserDefinedFunctions(Map<String, UDFParseNode> udfParseNodes) throws SQLException {
if (!connection
.getQueryServices()
.getProps()
.getBoolean(QueryServices.ALLOW_USER_DEFINED_FUNCTIONS_ATTRIB,
QueryServicesOptions.DEFAULT_ALLOW_USER_DEFINED_FUNCTIONS)) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.UNALLOWED_USER_DEFINED_FUNCTIONS)
- .build().buildException();
+ if(udfParseNodes.isEmpty()) {
+ throw new SQLExceptionInfo.Builder(SQLExceptionCode.UNALLOWED_USER_DEFINED_FUNCTIONS)
+ .build().buildException();
+ }
+ throw new FunctionNotFoundException(udfParseNodes.keySet().toString());
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/main/java/org/apache/phoenix/parse/CreateFunctionStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/CreateFunctionStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/CreateFunctionStatement.java
index 741e4df..863783b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/CreateFunctionStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/CreateFunctionStatement.java
@@ -20,10 +20,12 @@ package org.apache.phoenix.parse;
public class CreateFunctionStatement extends MutableStatement {
private final PFunction functionInfo;
private final boolean temporary;
+ private final boolean isReplace;
- public CreateFunctionStatement(PFunction functionInfo, boolean temporary) {
+ public CreateFunctionStatement(PFunction functionInfo, boolean temporary, boolean isReplace) {
this.functionInfo = functionInfo;
this.temporary = temporary;
+ this.isReplace = isReplace;
}
@Override
@@ -39,4 +41,7 @@ public class CreateFunctionStatement extends MutableStatement {
return temporary;
}
+ public boolean isReplace() {
+ return isReplace;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/main/java/org/apache/phoenix/parse/PFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/PFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/PFunction.java
index a1413de..a5263ad 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/PFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/PFunction.java
@@ -46,6 +46,7 @@ public class PFunction implements PMetaDataEntity {
private long timeStamp;
private int estimatedSize;
private boolean temporary;
+ private boolean replace;
public PFunction(long timeStamp) { // For index delete marker
this.timeStamp = timeStamp;
@@ -71,11 +72,23 @@ public class PFunction implements PMetaDataEntity {
public PFunction(PFunction function, boolean temporary) {
this(function.getTenantId(), function.getFunctionName(), function.getFunctionArguments(),
function.getReturnType(), function.getClassName(), function.getJarPath(), function
- .getTimeStamp(), temporary);
+ .getTimeStamp(), temporary, function.isReplace());
+ }
+
+ public PFunction(PFunction function, boolean temporary, boolean isReplace) {
+ this(function.getTenantId(), function.getFunctionName(), function.getFunctionArguments(),
+ function.getReturnType(), function.getClassName(), function.getJarPath(), function
+ .getTimeStamp(), temporary, isReplace);
+ }
+
+ public PFunction(PName tenantId, String functionName, List<FunctionArgument> args,
+ String returnType, String className, String jarPath, long timeStamp, boolean temporary) {
+ this(tenantId, functionName, args, returnType, className, jarPath, timeStamp, temporary,
+ false);
}
public PFunction(PName tenantId, String functionName, List<FunctionArgument> args, String returnType,
- String className, String jarPath, long timeStamp, boolean temporary) {
+ String className, String jarPath, long timeStamp, boolean temporary, boolean replace) {
this.tenantId = tenantId;
this.functionName = PNameFactory.newName(functionName);
if (args == null){
@@ -94,6 +107,7 @@ public class PFunction implements PMetaDataEntity {
PNameFactory.getEstimatedSize(this.className) +
(jarPath==null?0:PNameFactory.getEstimatedSize(this.jarPath));
this.temporary = temporary;
+ this.replace = replace;
}
public PFunction(PFunction function) {
@@ -217,6 +231,9 @@ public class PFunction implements PMetaDataEntity {
}
builder.addArguments(argBuilder.build());
}
+ if(builder.hasIsReplace()) {
+ builder.setIsReplace(function.isReplace());
+ }
return builder.build();
}
@@ -248,11 +265,16 @@ public class PFunction implements PMetaDataEntity {
minValue == null ? null : LiteralExpression.newConstant((new LiteralParseNode(dataType.toObject(minValue))).getValue()),
maxValue == null ? null : LiteralExpression.newConstant((new LiteralParseNode(dataType.toObject(maxValue))).getValue())));
}
- return new PFunction(tenantId,functionName, args, returnType, className, jarPath, timeStamp);
+ return new PFunction(tenantId, functionName, args, returnType, className, jarPath,
+ timeStamp, false, function.hasIsReplace() ? true : false);
}
public int getEstimatedSize() {
return estimatedSize;
}
+
+ public boolean isReplace() {
+ return this.replace;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
index 291c84c..44359a7 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
@@ -297,8 +297,8 @@ public class ParseNodeFactory {
maxValue, cycle, ifNotExits, bindCount);
}
- public CreateFunctionStatement createFunction(PFunction functionInfo, boolean temporary) {
- return new CreateFunctionStatement(functionInfo, temporary);
+ public CreateFunctionStatement createFunction(PFunction functionInfo, boolean temporary, boolean isReplace) {
+ return new CreateFunctionStatement(functionInfo, temporary, isReplace);
}
public DropFunctionStatement dropFunction(String functionName, boolean ifExists) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/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 ddebf9f..69520b0 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
@@ -2709,6 +2709,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
builder.addTableMetadataMutations(mp.toByteString());
}
builder.setTemporary(temporary);
+ builder.setReplace(function.isReplace());
instance.createFunction(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/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 d2d4338..9e74d2a 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
@@ -1348,7 +1348,7 @@ public class MetaDataClient {
boolean wasAutoCommit = connection.getAutoCommit();
connection.rollback();
try {
- PFunction function = new PFunction(stmt.getFunctionInfo(), stmt.isTemporary());
+ PFunction function = new PFunction(stmt.getFunctionInfo(), stmt.isTemporary(), stmt.isReplace());
connection.setAutoCommit(false);
String tenantIdStr = connection.getTenantId() == null ? null : connection.getTenantId().getString();
List<Mutation> functionData = Lists.newArrayListWithExpectedSize(function.getFunctionArguments().size() + 1);
@@ -1377,16 +1377,26 @@ public class MetaDataClient {
MutationCode code = result.getMutationCode();
switch(code) {
case FUNCTION_ALREADY_EXISTS:
- throw new FunctionAlreadyExistsException(function.getFunctionName(), result
+ if (!function.isReplace()) {
+ throw new FunctionAlreadyExistsException(function.getFunctionName(), result
.getFunctions().get(0));
+ } else {
+ connection.removeFunction(function.getTenantId(), function.getFunctionName(),
+ result.getMutationTime());
+ addFunctionToCache(result);
+ }
case NEWER_FUNCTION_FOUND:
- // Add function to ConnectionQueryServices so it's cached, but don't add
- // it to this connection as we can't see it.
- throw new NewerFunctionAlreadyExistsException(function.getFunctionName(), result.getFunctions().get(0));
+ // Add function to ConnectionQueryServices so it's cached, but don't add
+ // it to this connection as we can't see it.
+ throw new NewerFunctionAlreadyExistsException(function.getFunctionName(), result.getFunctions().get(0));
default:
List<PFunction> functions = new ArrayList<PFunction>(1);
functions.add(function);
result = new MetaDataMutationResult(code, result.getMutationTime(), functions, true);
+ if(function.isReplace()) {
+ connection.removeFunction(function.getTenantId(), function.getFunctionName(),
+ result.getMutationTime());
+ }
addFunctionToCache(result);
}
} finally {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/11bdb0ee/phoenix-protocol/src/main/PFunction.proto
----------------------------------------------------------------------
diff --git a/phoenix-protocol/src/main/PFunction.proto b/phoenix-protocol/src/main/PFunction.proto
index 07cbac7..0b44d5c 100644
--- a/phoenix-protocol/src/main/PFunction.proto
+++ b/phoenix-protocol/src/main/PFunction.proto
@@ -42,4 +42,5 @@ message PFunction {
optional bytes tenantId = 6;
optional string returnType = 7;
optional bool isArrayReturnType = 8;
+ optional bool isReplace = 9;
}
[37/50] [abbrv] phoenix git commit: PHOENIX-2111 Race condition on
creation of new view and adding of column to base table
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f09f1a5/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 feb5989..52b038b 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
@@ -18,6 +18,9 @@
package org.apache.phoenix.query;
import static org.apache.hadoop.hbase.HColumnDescriptor.TTL;
+import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_MAJOR_VERSION;
+import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_MINOR_VERSION;
+import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_PATCH_NUMBER;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES;
import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_DROP_METADATA;
import static org.apache.phoenix.util.UpgradeUtil.upgradeTo4_5_0;
@@ -110,6 +113,7 @@ import org.apache.phoenix.hbase.index.Indexer;
import org.apache.phoenix.hbase.index.covered.CoveredColumnsIndexBuilder;
import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
import org.apache.phoenix.hbase.index.util.KeyValueBuilder;
+import org.apache.phoenix.hbase.index.util.VersionUtil;
import org.apache.phoenix.index.PhoenixIndexBuilder;
import org.apache.phoenix.index.PhoenixIndexCodec;
import org.apache.phoenix.jdbc.PhoenixConnection;
@@ -966,7 +970,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
BlockingRpcCallback<GetVersionResponse> rpcCallback =
new BlockingRpcCallback<GetVersionResponse>();
GetVersionRequest.Builder builder = GetVersionRequest.newBuilder();
-
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.getVersion(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
@@ -1265,6 +1269,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
MutationProto mp = ProtobufUtil.toProto(m);
builder.addTableMetadataMutations(mp.toByteString());
}
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.createTable(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
@@ -1293,12 +1298,12 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
builder.setTableName(ByteStringer.wrap(tableBytes));
builder.setTableTimestamp(tableTimestamp);
builder.setClientTimestamp(clientTimestamp);
-
- instance.getTable(controller, builder.build(), rpcCallback);
- if(controller.getFailedOn() != null) {
- throw controller.getFailedOn();
- }
- return rpcCallback.get();
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
+ instance.getTable(controller, builder.build(), rpcCallback);
+ if(controller.getFailedOn() != null) {
+ throw controller.getFailedOn();
+ }
+ return rpcCallback.get();
}
});
}
@@ -1325,7 +1330,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
}
builder.setTableType(tableType.getSerializedValue());
builder.setCascade(cascade);
-
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.dropTable(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
@@ -1379,6 +1384,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
builder.addTableMetadataMutations(mp.toByteString());
}
builder.setIfExists(ifExists);
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.dropFunction(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
@@ -1553,7 +1559,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
MutationProto mp = ProtobufUtil.toProto(m);
builder.addTableMetadataMutations(mp.toByteString());
}
-
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.addColumn(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
@@ -1804,6 +1810,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
MutationProto mp = ProtobufUtil.toProto(m);
builder.addTableMetadataMutations(mp.toByteString());
}
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.dropColumn(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
@@ -2125,6 +2132,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
BlockingRpcCallback<ClearCacheResponse> rpcCallback =
new BlockingRpcCallback<ClearCacheResponse>();
ClearCacheRequest.Builder builder = ClearCacheRequest.newBuilder();
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.clearCache(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
@@ -2189,23 +2197,24 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
byte[] tableKey = SchemaUtil.getTableKey(ByteUtil.EMPTY_BYTE_ARRAY, rowKeyMetadata[PhoenixDatabaseMetaData.SCHEMA_NAME_INDEX], rowKeyMetadata[PhoenixDatabaseMetaData.TABLE_NAME_INDEX]);
return metaDataCoprocessorExec(tableKey,
new Batch.Call<MetaDataService, MetaDataResponse>() {
- @Override
- public MetaDataResponse call(MetaDataService instance) throws IOException {
- ServerRpcController controller = new ServerRpcController();
- BlockingRpcCallback<MetaDataResponse> rpcCallback =
- new BlockingRpcCallback<MetaDataResponse>();
- UpdateIndexStateRequest.Builder builder = UpdateIndexStateRequest.newBuilder();
- for (Mutation m : tableMetaData) {
- MutationProto mp = ProtobufUtil.toProto(m);
- builder.addTableMetadataMutations(mp.toByteString());
- }
- instance.updateIndexState(controller, builder.build(), rpcCallback);
- if(controller.getFailedOn() != null) {
- throw controller.getFailedOn();
- }
- return rpcCallback.get();
- }
- });
+ @Override
+ public MetaDataResponse call(MetaDataService instance) throws IOException {
+ ServerRpcController controller = new ServerRpcController();
+ BlockingRpcCallback<MetaDataResponse> rpcCallback =
+ new BlockingRpcCallback<MetaDataResponse>();
+ UpdateIndexStateRequest.Builder builder = UpdateIndexStateRequest.newBuilder();
+ for (Mutation m : tableMetaData) {
+ MutationProto mp = ProtobufUtil.toProto(m);
+ builder.addTableMetadataMutations(mp.toByteString());
+ }
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
+ instance.updateIndexState(controller, builder.build(), rpcCallback);
+ if(controller.getFailedOn() != null) {
+ throw controller.getFailedOn();
+ }
+ return rpcCallback.get();
+ }
+ });
}
@Override
@@ -2408,6 +2417,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
builder.setTableName(ByteStringer.wrap(tableName));
builder.setSchemaName(ByteStringer.wrap(schemaName));
builder.setClientTimestamp(clientTS);
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.clearTableFromCache(controller, builder.build(), rpcCallback);
if (controller.getFailedOn() != null) { throw controller.getFailedOn(); }
return rpcCallback.get();
@@ -2696,12 +2706,12 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
builder.addFunctionTimestamps(function.getSecond().longValue());
}
builder.setClientTimestamp(clientTimestamp);
-
- instance.getFunctions(controller, builder.build(), rpcCallback);
- if(controller.getFailedOn() != null) {
- throw controller.getFailedOn();
- }
- return rpcCallback.get();
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
+ instance.getFunctions(controller, builder.build(), rpcCallback);
+ if(controller.getFailedOn() != null) {
+ throw controller.getFailedOn();
+ }
+ return rpcCallback.get();
}
}, PhoenixDatabaseMetaData.SYSTEM_FUNCTION_NAME_BYTES);
@@ -2732,6 +2742,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
}
builder.setTemporary(temporary);
builder.setReplace(function.isReplace());
+ builder.setClientVersion(VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER));
instance.createFunction(controller, builder.build(), rpcCallback);
if(controller.getFailedOn() != null) {
throw controller.getFailedOn();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f09f1a5/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 b1fcf30..f74133a 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
@@ -234,8 +234,9 @@ public class MetaDataClient {
TABLE_SCHEM + "," +
TABLE_NAME + "," +
COLUMN_FAMILY + "," +
- LINK_TYPE +
- ") VALUES (?, ?, ?, ?, ?)";
+ LINK_TYPE + "," +
+ TABLE_SEQ_NUM + // this is actually set to the parent table's sequence number
+ ") VALUES (?, ?, ?, ?, ?, ?)";
private static final String CREATE_VIEW_LINK =
"UPSERT INTO " + SYSTEM_CATALOG_SCHEMA + ".\"" + SYSTEM_CATALOG_TABLE + "\"( " +
TENANT_ID + "," +
@@ -1490,6 +1491,7 @@ public class MetaDataClient {
linkStatement.setString(3, parentTableName);
linkStatement.setString(4, tableName);
linkStatement.setByte(5, LinkType.INDEX_TABLE.getSerializedValue());
+ linkStatement.setLong(6, parent.getSequenceNumber());
linkStatement.execute();
}
@@ -1649,6 +1651,12 @@ public class MetaDataClient {
linkStatement.setString(3, tableName);
linkStatement.setString(4, physicalName.getString());
linkStatement.setByte(5, LinkType.PHYSICAL_TABLE.getSerializedValue());
+ if (tableType == PTableType.VIEW) {
+ PTable physicalTable = connection.getMetaDataCache().getTable(new PTableKey(null, physicalName.getString()));
+ linkStatement.setLong(6, physicalTable.getSequenceNumber());
+ } else {
+ linkStatement.setLong(6, parent.getSequenceNumber());
+ }
linkStatement.execute();
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f09f1a5/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
index fbc15be..ee73a58 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
@@ -51,6 +51,7 @@ import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTable.LinkType;
import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.SequenceKey;
import org.apache.phoenix.schema.SortOrder;
@@ -59,6 +60,7 @@ import org.apache.phoenix.schema.types.PBoolean;
import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.schema.types.PLong;
import org.apache.phoenix.schema.types.PSmallint;
+import org.apache.phoenix.schema.types.PUnsignedTinyint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -437,4 +439,16 @@ public class MetaDataUtil {
scan.setStopRow(stopKey);
return scan;
}
+
+ public static LinkType getLinkType(Mutation tableMutation) {
+ List<Cell> kvs = tableMutation.getFamilyCellMap().get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES);
+ if (kvs != null) {
+ for (Cell kv : kvs) {
+ if (Bytes.compareTo(kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength(), PhoenixDatabaseMetaData.LINK_TYPE_BYTES, 0, PhoenixDatabaseMetaData.LINK_TYPE_BYTES.length) == 0) {
+ return LinkType.fromSerializedValue(PUnsignedTinyint.INSTANCE.getCodec().decodeByte(kv.getValueArray(), kv.getValueOffset(), SortOrder.getDefault()));
+ }
+ }
+ }
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f09f1a5/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 61642bc..1a2019d 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
@@ -83,8 +83,6 @@ import org.apache.phoenix.schema.RowKeyValueAccessor;
import org.apache.phoenix.schema.TableNotFoundException;
import org.apache.phoenix.schema.ValueBitSet;
import org.apache.phoenix.schema.types.PDataType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
@@ -99,8 +97,6 @@ import com.google.common.collect.Lists;
* @since 0.1
*/
public class PhoenixRuntime {
- private static final Logger logger = LoggerFactory.getLogger(PhoenixRuntime.class);
-
/**
* Use this connection property to control HBase timestamps
* by specifying your own long timestamp value at connection time. All
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f09f1a5/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
index 0ad6b9d..e1e2515 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
@@ -466,8 +466,8 @@ public class UpgradeUtil {
public static void upgradeTo4_5_0(PhoenixConnection oldMetaConnection) throws SQLException {
PhoenixConnection metaConnection = null;
try {
- // Need to use own connection without any SCN to be able to read all data from SYSTEM.CATALOG
- metaConnection = new PhoenixConnection(oldMetaConnection);
+ // Need to use own connection with max time stamp to be able to read all data from SYSTEM.CATALOG
+ metaConnection = new PhoenixConnection(oldMetaConnection, HConstants.LATEST_TIMESTAMP);
logger.info("Upgrading metadata to support adding columns to tables with views");
String getBaseTableAndViews = "SELECT "
+ COLUMN_FAMILY + " AS BASE_PHYSICAL_TABLE, "
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f09f1a5/phoenix-protocol/src/main/MetaDataService.proto
----------------------------------------------------------------------
diff --git a/phoenix-protocol/src/main/MetaDataService.proto b/phoenix-protocol/src/main/MetaDataService.proto
index e79f846..c265158 100644
--- a/phoenix-protocol/src/main/MetaDataService.proto
+++ b/phoenix-protocol/src/main/MetaDataService.proto
@@ -61,6 +61,7 @@ message GetTableRequest {
required bytes tableName = 3;
required int64 tableTimestamp = 4;
required int64 clientTimestamp = 5;
+ optional int32 clientVersion = 6;
}
message GetFunctionsRequest {
@@ -68,11 +69,13 @@ message GetFunctionsRequest {
repeated bytes functionNames = 2;
repeated int64 functionTimestamps = 3;
required int64 clientTimestamp = 4;
+ optional int32 clientVersion = 5;
}
// each byte array represents a MutationProto instance
message CreateTableRequest {
- repeated bytes tableMetadataMutations = 1;
+ repeated bytes tableMetadataMutations = 1;
+ optional int32 clientVersion = 2;
}
// each byte array represents a MutationProto instance
@@ -80,38 +83,46 @@ message CreateFunctionRequest {
repeated bytes tableMetadataMutations = 1;
required bool temporary = 2;
optional bool replace = 3;
+ optional int32 clientVersion = 4;
}
message DropTableRequest {
repeated bytes tableMetadataMutations = 1;
required string tableType = 2;
optional bool cascade = 3;
+ optional int32 clientVersion = 4;
}
message AddColumnRequest {
repeated bytes tableMetadataMutations = 1;
+ optional int32 clientVersion = 2;
}
message DropColumnRequest {
repeated bytes tableMetadataMutations = 1;
+ optional int32 clientVersion = 2;
}
message DropFunctionRequest {
repeated bytes tableMetadataMutations = 1;
optional bool ifExists = 2;
+ optional int32 clientVersion = 3;
}
message UpdateIndexStateRequest {
repeated bytes tableMetadataMutations = 1;
+ optional int32 clientVersion = 2;
}
message ClearCacheRequest {
+ optional int32 clientVersion = 1;
}
message ClearCacheResponse {
}
message GetVersionRequest {
+ optional int32 clientVersion = 1;
}
message GetVersionResponse {
@@ -123,6 +134,7 @@ message ClearTableFromCacheRequest {
required bytes schemaName = 2;
required bytes tableName = 3;
required int64 clientTimestamp = 4;
+ optional int32 clientVersion = 5;
}
message ClearTableFromCacheResponse {
[06/50] [abbrv] phoenix git commit: PHOENIX-2036
PhoenixConfigurationUtil should provide a pre-normalize table name to
PhoenixRuntime
Posted by ma...@apache.org.
PHOENIX-2036 PhoenixConfigurationUtil should provide a pre-normalize table name to PhoenixRuntime
Update phoenix-spark to follow the same normalization requirement.
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/39c982f9
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/39c982f9
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/39c982f9
Branch: refs/heads/calcite
Commit: 39c982f923033b97c477464d0c4e27221421774d
Parents: 1e606d5
Author: Josh Mahonin <jm...@gmail.com>
Authored: Mon Jul 6 19:39:31 2015 -0400
Committer: Josh Mahonin <jm...@apache.org>
Committed: Mon Jul 6 19:41:38 2015 -0400
----------------------------------------------------------------------
phoenix-spark/src/it/resources/setup.sql | 4 +-
.../apache/phoenix/spark/PhoenixSparkIT.scala | 58 ++++++++++++--------
.../org/apache/phoenix/spark/PhoenixRDD.scala | 24 +++-----
3 files changed, 46 insertions(+), 40 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/39c982f9/phoenix-spark/src/it/resources/setup.sql
----------------------------------------------------------------------
diff --git a/phoenix-spark/src/it/resources/setup.sql b/phoenix-spark/src/it/resources/setup.sql
index 40157a2..154a996 100644
--- a/phoenix-spark/src/it/resources/setup.sql
+++ b/phoenix-spark/src/it/resources/setup.sql
@@ -32,4 +32,6 @@ CREATE TABLE ARRAY_TEST_TABLE (ID BIGINT NOT NULL PRIMARY KEY, VCARRAY VARCHAR[]
UPSERT INTO ARRAY_TEST_TABLE (ID, VCARRAY) VALUES (1, ARRAY['String1', 'String2', 'String3'])
CREATE TABLE DATE_PREDICATE_TEST_TABLE (ID BIGINT NOT NULL, TIMESERIES_KEY TIMESTAMP NOT NULL CONSTRAINT pk PRIMARY KEY (ID, TIMESERIES_KEY))
UPSERT INTO DATE_PREDICATE_TEST_TABLE (ID, TIMESERIES_KEY) VALUES (1, CAST(CURRENT_TIME() AS TIMESTAMP))
-CREATE TABLE OUTPUT_TEST_TABLE (id BIGINT NOT NULL PRIMARY KEY, col1 VARCHAR, col2 INTEGER, col3 DATE)
\ No newline at end of file
+CREATE TABLE OUTPUT_TEST_TABLE (id BIGINT NOT NULL PRIMARY KEY, col1 VARCHAR, col2 INTEGER, col3 DATE)
+CREATE TABLE CUSTOM_ENTITY."z02"(id BIGINT NOT NULL PRIMARY KEY)
+UPSERT INTO CUSTOM_ENTITY."z02" (id) VALUES(1)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/39c982f9/phoenix-spark/src/it/scala/org/apache/phoenix/spark/PhoenixSparkIT.scala
----------------------------------------------------------------------
diff --git a/phoenix-spark/src/it/scala/org/apache/phoenix/spark/PhoenixSparkIT.scala b/phoenix-spark/src/it/scala/org/apache/phoenix/spark/PhoenixSparkIT.scala
index 5f256e6..e1c9df4 100644
--- a/phoenix-spark/src/it/scala/org/apache/phoenix/spark/PhoenixSparkIT.scala
+++ b/phoenix-spark/src/it/scala/org/apache/phoenix/spark/PhoenixSparkIT.scala
@@ -20,9 +20,9 @@ import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.hbase.{HBaseConfiguration, HConstants, HBaseTestingUtility}
import org.apache.phoenix.end2end.BaseHBaseManagedTimeIT
import org.apache.phoenix.query.BaseTest
-import org.apache.phoenix.schema.ColumnNotFoundException
+import org.apache.phoenix.schema.{TableNotFoundException, ColumnNotFoundException}
import org.apache.phoenix.schema.types.PVarchar
-import org.apache.phoenix.util.ColumnInfo
+import org.apache.phoenix.util.{SchemaUtil, ColumnInfo}
import org.apache.spark.sql.{SaveMode, execution, SQLContext}
import org.apache.spark.sql.types.{LongType, DataType, StringType, StructField}
import org.apache.spark.{SparkConf, SparkContext}
@@ -96,23 +96,6 @@ class PhoenixSparkIT extends FunSuite with Matchers with BeforeAndAfterAll {
PhoenixSparkITHelper.doTeardown
}
- def buildSql(table: String, columns: Seq[String], predicate: Option[String]): String = {
- val query = "SELECT %s FROM \"%s\"" format(columns.map(f => "\"" + f + "\"").mkString(", "), table)
-
- query + (predicate match {
- case Some(p: String) => " WHERE " + p
- case _ => ""
- })
- }
-
- test("Can create valid SQL") {
- val rdd = new PhoenixRDD(sc, "MyTable", Array("Foo", "Bar"),
- conf = hbaseConfiguration)
-
- rdd.buildSql("MyTable", Array("Foo", "Bar"), None) should
- equal("SELECT \"Foo\", \"Bar\" FROM \"MyTable\"")
- }
-
test("Can convert Phoenix schema") {
val phoenixSchema = List(
new ColumnInfo("varcharColumn", PVarchar.INSTANCE.getSqlType)
@@ -154,7 +137,9 @@ class PhoenixSparkIT extends FunSuite with Matchers with BeforeAndAfterAll {
val sqlContext = new SQLContext(sc)
- val df1 = sqlContext.phoenixTableAsDataFrame("table3", Array("id", "col1"),
+ val df1 = sqlContext.phoenixTableAsDataFrame(
+ SchemaUtil.getEscapedArgument("table3"),
+ Array("id", "col1"),
zkUrl = Some(quorumAddress))
df1.registerTempTable("table3")
@@ -191,10 +176,12 @@ class PhoenixSparkIT extends FunSuite with Matchers with BeforeAndAfterAll {
}
test("Using a predicate referring to a non-existent column should fail") {
- intercept[RuntimeException] {
+ intercept[Exception] {
val sqlContext = new SQLContext(sc)
- val df1 = sqlContext.phoenixTableAsDataFrame("table3", Array("id", "col1"),
+ val df1 = sqlContext.phoenixTableAsDataFrame(
+ SchemaUtil.getEscapedArgument("table3"),
+ Array("id", "col1"),
predicate = Some("foo = bar"),
conf = hbaseConfiguration)
@@ -210,7 +197,9 @@ class PhoenixSparkIT extends FunSuite with Matchers with BeforeAndAfterAll {
test("Can create schema RDD with predicate that will never match") {
val sqlContext = new SQLContext(sc)
- val df1 = sqlContext.phoenixTableAsDataFrame("table3", Array("id", "col1"),
+ val df1 = sqlContext.phoenixTableAsDataFrame(
+ SchemaUtil.getEscapedArgument("table3"),
+ Array("id", "col1"),
predicate = Some("\"id\" = -1"),
conf = hbaseConfiguration)
@@ -436,4 +425,27 @@ class PhoenixSparkIT extends FunSuite with Matchers with BeforeAndAfterAll {
// Verify the arrays are equal
sqlArray shouldEqual dataSet(0)._2
}
+
+ test("Can read from table with schema and escaped table name") {
+ // Manually escape
+ val rdd1 = sc.phoenixTableAsRDD(
+ "CUSTOM_ENTITY.\"z02\"",
+ Seq("ID"),
+ conf = hbaseConfiguration)
+
+ var count = rdd1.count()
+
+ count shouldEqual 1L
+
+ // Use SchemaUtil
+ val rdd2 = sc.phoenixTableAsRDD(
+ SchemaUtil.getEscapedFullTableName("CUSTOM_ENTITY.z02"),
+ Seq("ID"),
+ conf = hbaseConfiguration)
+
+ count = rdd2.count()
+
+ count shouldEqual 1L
+
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/39c982f9/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRDD.scala
----------------------------------------------------------------------
diff --git a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRDD.scala b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRDD.scala
index 773026d..427fb24 100644
--- a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRDD.scala
+++ b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRDD.scala
@@ -63,30 +63,22 @@ class PhoenixRDD(sc: SparkContext, table: String, columns: Seq[String],
}
}
- def buildSql(table: String, columns: Seq[String], predicate: Option[String]): String = {
- val query = "SELECT %s FROM \"%s\"".format(
- if (columns.isEmpty) "*" else columns.map(f => "\"" + f + "\"").mkString(", "),
- table
- )
-
- query + (predicate match {
- case Some(p: String) if p.length > 0 => " WHERE " + p
- case _ => ""
- })
- }
-
def getPhoenixConfiguration: Configuration = {
// This is just simply not serializable, so don't try, but clone it because
// PhoenixConfigurationUtil mutates it.
val config = HBaseConfiguration.create(conf)
- PhoenixConfigurationUtil.setInputQuery(config, buildSql(table, columns, predicate))
+ PhoenixConfigurationUtil.setInputClass(config, classOf[PhoenixRecordWritable])
+ PhoenixConfigurationUtil.setInputTableName(config, table)
+
if(!columns.isEmpty) {
- PhoenixConfigurationUtil.setSelectColumnNames(config, columns.mkString(","))
+ PhoenixConfigurationUtil.setSelectColumnNames(config, columns.toArray)
+ }
+
+ if(predicate.isDefined) {
+ PhoenixConfigurationUtil.setInputTableConditions(config, predicate.get)
}
- PhoenixConfigurationUtil.setInputTableName(config, table)
- PhoenixConfigurationUtil.setInputClass(config, classOf[PhoenixRecordWritable])
// Override the Zookeeper URL if present. Throw exception if no address given.
zkUrl match {
[46/50] [abbrv] phoenix git commit: PHOENIX-1890 Provide queries for
adding/deleting jars to/from common place in hdfs which is used by dynamic
class loader(Rajeshbabu)
Posted by ma...@apache.org.
PHOENIX-1890 Provide queries for adding/deleting jars to/from common place in hdfs which is used by dynamic class loader(Rajeshbabu)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/f006df54
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/f006df54
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/f006df54
Branch: refs/heads/calcite
Commit: f006df5451859eb9d22130bb46b58460eee49674
Parents: 236ce1c
Author: Rajeshbabu Chintaguntla <ra...@apache.org>
Authored: Thu Jul 16 23:18:38 2015 +0530
Committer: Rajeshbabu Chintaguntla <ra...@apache.org>
Committed: Thu Jul 16 23:18:38 2015 +0530
----------------------------------------------------------------------
.../phoenix/end2end/UserDefinedFunctionsIT.java | 67 ++++--
phoenix-core/src/main/antlr3/PhoenixSQL.g | 23 ++
.../phoenix/compile/ListJarsQueryPlan.java | 216 +++++++++++++++++++
.../apache/phoenix/jdbc/PhoenixStatement.java | 175 +++++++++++++++
.../apache/phoenix/parse/AddJarsStatement.java | 38 ++++
.../phoenix/parse/DeleteJarStatement.java | 19 ++
.../apache/phoenix/parse/ListJarsStatement.java | 34 +++
.../apache/phoenix/parse/ParseNodeFactory.java | 12 ++
8 files changed, 564 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/f006df54/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java
index e2b7b4c..cd1e380 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UserDefinedFunctionsIT.java
@@ -207,9 +207,6 @@ public class UserDefinedFunctionsIT extends BaseOwnClusterIT{
conf.set(DYNAMIC_JARS_DIR_KEY, string+"/hbase/tmpjars");
util.startMiniHBaseCluster(1, 1);
UDFExpression.setConfig(conf);
- compileTestClass(MY_REVERSE_CLASS_NAME, MY_REVERSE_PROGRAM, 1);
- compileTestClass(MY_SUM_CLASS_NAME, MY_SUM_PROGRAM, 2);
- compileTestClass(MY_ARRAY_INDEX_CLASS_NAME, MY_ARRAY_INDEX_PROGRAM, 3);
String clientPort = util.getConfiguration().get(QueryServices.ZOOKEEPER_PORT_ATTRIB);
url =
@@ -217,10 +214,54 @@ public class UserDefinedFunctionsIT extends BaseOwnClusterIT{
+ clientPort + JDBC_PROTOCOL_TERMINATOR + PHOENIX_TEST_DRIVER_URL_PARAM;
Map<String, String> props = Maps.newHashMapWithExpectedSize(1);
props.put(QueryServices.ALLOW_USER_DEFINED_FUNCTIONS_ATTRIB, "true");
+ props.put(QueryServices.DYNAMIC_JARS_DIR_KEY,string+"/hbase/tmpjars/");
driver = initAndRegisterDriver(url, new ReadOnlyProps(props.entrySet().iterator()));
+ compileTestClass(MY_REVERSE_CLASS_NAME, MY_REVERSE_PROGRAM, 1);
+ compileTestClass(MY_SUM_CLASS_NAME, MY_SUM_PROGRAM, 2);
+ compileTestClass(MY_ARRAY_INDEX_CLASS_NAME, MY_ARRAY_INDEX_PROGRAM, 3);
+ compileTestClass(MY_ARRAY_INDEX_CLASS_NAME, MY_ARRAY_INDEX_PROGRAM, 4);
}
@Test
+ public void testListJars() throws Exception {
+ Connection conn = driver.connect(url, EMPTY_PROPS);
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery("list jars");
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar1.jar", rs.getString("jar_location"));
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar2.jar", rs.getString("jar_location"));
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar3.jar", rs.getString("jar_location"));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testDeleteJar() throws Exception {
+ Connection conn = driver.connect(url, EMPTY_PROPS);
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery("list jars");
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar1.jar", rs.getString("jar_location"));
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar2.jar", rs.getString("jar_location"));
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar3.jar", rs.getString("jar_location"));
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar4.jar", rs.getString("jar_location"));
+ assertFalse(rs.next());
+ stmt.execute("delete jar '"+ util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar4.jar'");
+ rs = stmt.executeQuery("list jars");
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar1.jar", rs.getString("jar_location"));
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar2.jar", rs.getString("jar_location"));
+ assertTrue(rs.next());
+ assertEquals(util.getConfiguration().get(QueryServices.DYNAMIC_JARS_DIR_KEY)+"/"+"myjar3.jar", rs.getString("jar_location"));
+ assertFalse(rs.next());
+ }
+
+ @Test
public void testCreateFunction() throws Exception {
Connection conn = driver.connect(url, EMPTY_PROPS);
Statement stmt = conn.createStatement();
@@ -776,23 +817,9 @@ public class UserDefinedFunctionsIT extends BaseOwnClusterIT{
jarFos.close();
assertTrue(jarFile.exists());
-
- InputStream inputStream = new BufferedInputStream(new FileInputStream(jarPath));
- FileSystem fs = util.getDefaultRootDirPath().getFileSystem(util.getConfiguration());
- Path jarsLocation = new Path(util.getConfiguration().get(DYNAMIC_JARS_DIR_KEY));
- Path myJarPath;
- if (jarsLocation.toString().endsWith("/")) {
- myJarPath = new Path(jarsLocation.toString() + jarName);
- } else {
- myJarPath = new Path(jarsLocation.toString() + "/" + jarName);
- }
- OutputStream outputStream = fs.create(myJarPath);
- try {
- IOUtils.copyBytes(inputStream, outputStream, 4096, false);
- } finally {
- IOUtils.closeStream(inputStream);
- IOUtils.closeStream(outputStream);
- }
+ Connection conn = driver.connect(url, EMPTY_PROPS);
+ Statement stmt = conn.createStatement();
+ stmt.execute("add jars '"+jarFile.getAbsolutePath()+"'");
} finally {
if (javaFile != null) javaFile.delete();
if (classFile != null) classFile.delete();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/f006df54/phoenix-core/src/main/antlr3/PhoenixSQL.g
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g
index 10fda68..9fde48f 100644
--- a/phoenix-core/src/main/antlr3/PhoenixSQL.g
+++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g
@@ -123,6 +123,8 @@ tokens
DEFAULTVALUE='defaultvalue';
CONSTANT = 'constant';
REPLACE = 'replace';
+ LIST = 'list';
+ JARS='jars';
}
@@ -182,6 +184,7 @@ import org.apache.phoenix.schema.types.PUnsignedTimestamp;
import org.apache.phoenix.util.SchemaUtil;
import org.apache.phoenix.parse.LikeParseNode.LikeType;
import org.apache.phoenix.trace.util.Tracing;
+import org.apache.phoenix.parse.AddJarsStatement;
}
@lexer::header {
@@ -398,6 +401,9 @@ oneStatement returns [BindableStatement ret]
| s=trace_node
| s=create_function_node
| s=drop_function_node
+ | s=add_jars_node
+ | s=list_jars_node
+ | s=delete_jar_node
| s=alter_session_node
| s=create_sequence_node
| s=drop_sequence_node
@@ -558,6 +564,18 @@ drop_function_node returns [DropFunctionStatement ret]
: DROP FUNCTION (IF ex=EXISTS)? function=identifier {$ret = factory.dropFunction(SchemaUtil.normalizeIdentifier(function), ex!=null);}
;
+add_jars_node returns [AddJarsStatement ret]
+ : ADD JARS jarPaths = one_or_more_jarpaths { $ret = factory.addJars(jarPaths);}
+ ;
+
+list_jars_node returns [ListJarsStatement ret]
+ : LIST JARS { $ret = factory.listJars();}
+ ;
+
+delete_jar_node returns [DeleteJarStatement ret]
+ : DELETE JAR jarPath = jar_path { $ret = factory.deleteJar(jarPath);}
+ ;
+
// Parse an alter session statement.
alter_session_node returns [AlterSessionStatement ret]
: ALTER SESSION (SET p=properties)
@@ -914,6 +932,11 @@ one_or_more_expressions returns [List<ParseNode> ret]
: e = expression {$ret.add(e);} (COMMA e = expression {$ret.add(e);} )*
;
+one_or_more_jarpaths returns [List<LiteralParseNode> ret]
+@init{ret = new ArrayList<LiteralParseNode>(); }
+ : jarPath = jar_path {$ret.add(jarPath);} (COMMA jarPath = jar_path {$ret.add(jarPath);} )*
+ ;
+
zero_or_more_expressions returns [List<ParseNode> ret]
@init{ret = new ArrayList<ParseNode>(); }
: (v = expression {$ret.add(v);})? (COMMA v = expression {$ret.add(v);} )*
http://git-wip-us.apache.org/repos/asf/phoenix/blob/f006df54/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
new file mode 100644
index 0000000..9fdf35b
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
@@ -0,0 +1,216 @@
+package org.apache.phoenix.compile;
+
+import java.io.IOException;
+import java.sql.ParameterMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.LocatedFileStatus;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.RemoteIterator;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellUtil;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.KeyValue.Type;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
+import org.apache.phoenix.expression.Determinism;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.expression.RowKeyColumnExpression;
+import org.apache.phoenix.iterate.DefaultParallelScanGrouper;
+import org.apache.phoenix.iterate.ParallelScanGrouper;
+import org.apache.phoenix.iterate.ResultIterator;
+import org.apache.phoenix.jdbc.PhoenixParameterMetaData;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.FilterableStatement;
+import org.apache.phoenix.parse.LiteralParseNode;
+import org.apache.phoenix.parse.ParseNodeFactory;
+import org.apache.phoenix.query.HBaseFactoryProvider;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PColumnImpl;
+import org.apache.phoenix.schema.PNameFactory;
+import org.apache.phoenix.schema.RowKeyValueAccessor;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.TableRef;
+import org.apache.phoenix.schema.tuple.ResultTuple;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PVarchar;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.SizedUtil;
+
+public class ListJarsQueryPlan implements QueryPlan {
+
+ private PhoenixStatement stmt = null;
+ private StatementContext context = null;
+ private boolean first = true;
+
+ private static final RowProjector JARS_PROJECTOR;
+
+ static {
+ List<ExpressionProjector> projectedColumns = new ArrayList<ExpressionProjector>();
+ PColumn column =
+ new PColumnImpl(PNameFactory.newName("jar_location"), null,
+ PVarchar.INSTANCE, null, null, false, 0, SortOrder.getDefault(), 0, null,
+ false, null);
+ List<PColumn> columns = new ArrayList<PColumn>();
+ columns.add(column);
+ Expression expression =
+ new RowKeyColumnExpression(column, new RowKeyValueAccessor(columns, 0));
+ projectedColumns.add(new ExpressionProjector("jar_location", "", expression,
+ true));
+ int estimatedByteSize = SizedUtil.KEY_VALUE_SIZE;
+ JARS_PROJECTOR = new RowProjector(projectedColumns, estimatedByteSize, false);
+ }
+
+ public ListJarsQueryPlan(PhoenixStatement stmt) {
+ this.stmt = stmt;
+ this.context = new StatementContext(stmt);
+ }
+
+ @Override
+ public StatementContext getContext() {
+ return this.context;
+ }
+
+ @Override
+ public ParameterMetaData getParameterMetaData() {
+ return PhoenixParameterMetaData.EMPTY_PARAMETER_META_DATA;
+ }
+
+ @Override
+ public ExplainPlan getExplainPlan() throws SQLException {
+ return ExplainPlan.EMPTY_PLAN;
+ }
+
+ @Override
+ public ResultIterator iterator() throws SQLException {
+ return iterator(DefaultParallelScanGrouper.getInstance());
+ }
+
+ @Override
+ public ResultIterator iterator(ParallelScanGrouper scanGrouper) throws SQLException {
+ return new ResultIterator() {
+ private RemoteIterator<LocatedFileStatus> listFiles = null;
+
+ @Override
+ public void close() throws SQLException {
+
+ }
+
+ @Override
+ public Tuple next() throws SQLException {
+ try {
+ if(first) {
+ String dynamicJarsDir =
+ stmt.getConnection().getQueryServices().getProps()
+ .get(QueryServices.DYNAMIC_JARS_DIR_KEY);
+ if(dynamicJarsDir == null) {
+ throw new SQLException(QueryServices.DYNAMIC_JARS_DIR_KEY
+ + " is not configured for the listing the jars.");
+ }
+ dynamicJarsDir =
+ dynamicJarsDir.endsWith("/") ? dynamicJarsDir : dynamicJarsDir + '/';
+ Configuration conf = HBaseFactoryProvider.getConfigurationFactory().getConfiguration();
+ Path dynamicJarsDirPath = new Path(dynamicJarsDir);
+ FileSystem fs = dynamicJarsDirPath.getFileSystem(conf);
+ listFiles = fs.listFiles(dynamicJarsDirPath, true);
+ first = false;
+ }
+ if(listFiles == null || !listFiles.hasNext()) return null;
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ ParseNodeFactory factory = new ParseNodeFactory();
+ LiteralParseNode literal =
+ factory.literal(listFiles.next().getPath().toString());
+ LiteralExpression expression =
+ LiteralExpression.newConstant(literal.getValue(), PVarchar.INSTANCE,
+ Determinism.ALWAYS);
+ expression.evaluate(null, ptr);
+ byte[] rowKey = ByteUtil.copyKeyBytesIfNecessary(ptr);
+ Cell cell =
+ CellUtil.createCell(rowKey, HConstants.EMPTY_BYTE_ARRAY,
+ HConstants.EMPTY_BYTE_ARRAY, System.currentTimeMillis(),
+ Type.Put.getCode(), HConstants.EMPTY_BYTE_ARRAY);
+ List<Cell> cells = new ArrayList<Cell>(1);
+ cells.add(cell);
+ return new ResultTuple(Result.create(cells));
+ } catch (IOException e) {
+ throw new SQLException(e);
+ }
+ }
+
+ @Override
+ public void explain(List<String> planSteps) {
+ }
+ };
+ }
+
+ @Override
+ public long getEstimatedSize() {
+ return PVarchar.INSTANCE.getByteSize();
+ }
+
+ @Override
+ public TableRef getTableRef() {
+ return null;
+ }
+
+ @Override
+ public RowProjector getProjector() {
+ return JARS_PROJECTOR;
+ }
+
+ @Override
+ public Integer getLimit() {
+ return null;
+ }
+
+ @Override
+ public OrderBy getOrderBy() {
+ return OrderBy.EMPTY_ORDER_BY;
+ }
+
+ @Override
+ public GroupBy getGroupBy() {
+ return GroupBy.EMPTY_GROUP_BY;
+ }
+
+ @Override
+ public List<KeyRange> getSplits() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<List<Scan>> getScans() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public FilterableStatement getStatement() {
+ return null;
+ }
+
+ @Override
+ public boolean isDegenerate() {
+ return false;
+ }
+
+ @Override
+ public boolean isRowKeyOrdered() {
+ return false;
+ }
+
+ @Override
+ public boolean useRoundRobinIterator() {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/f006df54/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
index 9689589..056263a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
@@ -21,6 +21,7 @@ import static org.apache.phoenix.monitoring.GlobalClientMetrics.GLOBAL_MUTATION_
import static org.apache.phoenix.monitoring.GlobalClientMetrics.GLOBAL_QUERY_TIME;
import static org.apache.phoenix.monitoring.GlobalClientMetrics.GLOBAL_SELECT_SQL_COUNTER;
+import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.sql.ParameterMetaData;
@@ -36,6 +37,11 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.LocatedFileStatus;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.hbase.client.Consistency;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Pair;
@@ -52,6 +58,7 @@ import org.apache.phoenix.compile.ExplainPlan;
import org.apache.phoenix.compile.ExpressionProjector;
import org.apache.phoenix.compile.FromCompiler;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.compile.ListJarsQueryPlan;
import org.apache.phoenix.compile.MutationPlan;
import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.compile.QueryCompiler;
@@ -74,6 +81,7 @@ import org.apache.phoenix.iterate.MaterializedResultIterator;
import org.apache.phoenix.iterate.ParallelScanGrouper;
import org.apache.phoenix.iterate.ResultIterator;
import org.apache.phoenix.parse.AddColumnStatement;
+import org.apache.phoenix.parse.AddJarsStatement;
import org.apache.phoenix.parse.AliasedNode;
import org.apache.phoenix.parse.AlterIndexStatement;
import org.apache.phoenix.parse.AlterSessionStatement;
@@ -84,6 +92,7 @@ import org.apache.phoenix.parse.CreateFunctionStatement;
import org.apache.phoenix.parse.CreateIndexStatement;
import org.apache.phoenix.parse.CreateSequenceStatement;
import org.apache.phoenix.parse.CreateTableStatement;
+import org.apache.phoenix.parse.DeleteJarStatement;
import org.apache.phoenix.parse.DeleteStatement;
import org.apache.phoenix.parse.DropColumnStatement;
import org.apache.phoenix.parse.DropFunctionStatement;
@@ -95,6 +104,8 @@ import org.apache.phoenix.parse.FilterableStatement;
import org.apache.phoenix.parse.HintNode;
import org.apache.phoenix.parse.IndexKeyConstraint;
import org.apache.phoenix.parse.LimitNode;
+import org.apache.phoenix.parse.ListJarsStatement;
+import org.apache.phoenix.parse.LiteralParseNode;
import org.apache.phoenix.parse.NamedNode;
import org.apache.phoenix.parse.NamedTableNode;
import org.apache.phoenix.parse.OrderByNode;
@@ -110,6 +121,7 @@ import org.apache.phoenix.parse.TraceStatement;
import org.apache.phoenix.parse.UDFParseNode;
import org.apache.phoenix.parse.UpdateStatisticsStatement;
import org.apache.phoenix.parse.UpsertStatement;
+import org.apache.phoenix.query.HBaseFactoryProvider;
import org.apache.phoenix.query.KeyRange;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.query.QueryServices;
@@ -631,6 +643,152 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
}
}
+ private static class ExecutableAddJarsStatement extends AddJarsStatement implements CompilableStatement {
+
+ public ExecutableAddJarsStatement(List<LiteralParseNode> jarPaths) {
+ super(jarPaths);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public MutationPlan compilePlan(final PhoenixStatement stmt, Sequence.ValueOp seqAction) throws SQLException {
+ final StatementContext context = new StatementContext(stmt);
+ return new MutationPlan() {
+
+ @Override
+ public StatementContext getContext() {
+ return context;
+ }
+
+ @Override
+ public ParameterMetaData getParameterMetaData() {
+ return PhoenixParameterMetaData.EMPTY_PARAMETER_META_DATA;
+ }
+
+ @Override
+ public ExplainPlan getExplainPlan() throws SQLException {
+ return new ExplainPlan(Collections.singletonList("ADD JARS"));
+ }
+
+ @Override
+ public PhoenixConnection getConnection() {
+ return stmt.getConnection();
+ }
+
+ @Override
+ public MutationState execute() throws SQLException {
+ String dynamicJarsDir = stmt.getConnection().getQueryServices().getProps().get(QueryServices.DYNAMIC_JARS_DIR_KEY);
+ if(dynamicJarsDir == null) {
+ throw new SQLException(QueryServices.DYNAMIC_JARS_DIR_KEY+" is not configured for placing the jars.");
+ }
+ dynamicJarsDir =
+ dynamicJarsDir.endsWith("/") ? dynamicJarsDir : dynamicJarsDir + '/';
+ Configuration conf = HBaseFactoryProvider.getConfigurationFactory().getConfiguration();
+ Path dynamicJarsDirPath = new Path(dynamicJarsDir);
+ for (LiteralParseNode jarPath : getJarPaths()) {
+ String jarPathStr = (String)jarPath.getValue();
+ if(!jarPathStr.endsWith(".jar")) {
+ throw new SQLException(jarPathStr + " is not a valid jar file path.");
+ }
+ }
+
+ try {
+ FileSystem fs = dynamicJarsDirPath.getFileSystem(conf);
+ List<LiteralParseNode> jarPaths = getJarPaths();
+ for (LiteralParseNode jarPath : jarPaths) {
+ File f = new File((String) jarPath.getValue());
+ fs.copyFromLocalFile(new Path(f.getAbsolutePath()), new Path(
+ dynamicJarsDir + f.getName()));
+ }
+ } catch(IOException e) {
+ throw new SQLException(e);
+ }
+ return new MutationState(0, context.getConnection());
+ }
+ };
+
+ }
+ }
+
+ private static class ExecutableDeleteJarStatement extends DeleteJarStatement implements CompilableStatement {
+
+ public ExecutableDeleteJarStatement(LiteralParseNode jarPath) {
+ super(jarPath);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public MutationPlan compilePlan(final PhoenixStatement stmt, Sequence.ValueOp seqAction) throws SQLException {
+ final StatementContext context = new StatementContext(stmt);
+ return new MutationPlan() {
+
+ @Override
+ public StatementContext getContext() {
+ return context;
+ }
+
+ @Override
+ public ParameterMetaData getParameterMetaData() {
+ return PhoenixParameterMetaData.EMPTY_PARAMETER_META_DATA;
+ }
+
+ @Override
+ public ExplainPlan getExplainPlan() throws SQLException {
+ return new ExplainPlan(Collections.singletonList("DELETE JAR"));
+ }
+
+ @Override
+ public PhoenixConnection getConnection() {
+ return stmt.getConnection();
+ }
+
+ @Override
+ public MutationState execute() throws SQLException {
+ String dynamicJarsDir = stmt.getConnection().getQueryServices().getProps().get(QueryServices.DYNAMIC_JARS_DIR_KEY);
+ if (dynamicJarsDir == null) {
+ throw new SQLException(QueryServices.DYNAMIC_JARS_DIR_KEY
+ + " is not configured.");
+ }
+ dynamicJarsDir =
+ dynamicJarsDir.endsWith("/") ? dynamicJarsDir : dynamicJarsDir + '/';
+ Configuration conf = HBaseFactoryProvider.getConfigurationFactory().getConfiguration();
+ Path dynamicJarsDirPath = new Path(dynamicJarsDir);
+ try {
+ FileSystem fs = dynamicJarsDirPath.getFileSystem(conf);
+ String jarPathStr = (String)getJarPath().getValue();
+ if(!jarPathStr.endsWith(".jar")) {
+ throw new SQLException(jarPathStr + " is not a valid jar file path.");
+ }
+ Path p = new Path(jarPathStr);
+ if(fs.exists(p)) {
+ fs.delete(p, false);
+ }
+ } catch(IOException e) {
+ throw new SQLException(e);
+ }
+ return new MutationState(0, context.getConnection());
+ }
+ };
+
+ }
+ }
+
+ private static class ExecutableListJarsStatement extends ListJarsStatement implements CompilableStatement {
+
+ public ExecutableListJarsStatement() {
+ super();
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public QueryPlan compilePlan(final PhoenixStatement stmt, Sequence.ValueOp seqAction) throws SQLException {
+ return new ListJarsQueryPlan(stmt);
+ }
+ }
+
private static class ExecutableCreateIndexStatement extends CreateIndexStatement implements CompilableStatement {
public ExecutableCreateIndexStatement(NamedNode indexName, NamedTableNode dataTable, IndexKeyConstraint ikConstraint, List<ColumnName> includeColumns, List<ParseNode> splits,
@@ -1026,6 +1184,23 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
public CreateFunctionStatement createFunction(PFunction functionInfo, boolean temporary, boolean isReplace) {
return new ExecutableCreateFunctionStatement(functionInfo, temporary, isReplace);
}
+
+ @Override
+ public AddJarsStatement addJars(List<LiteralParseNode> jarPaths) {
+ return new ExecutableAddJarsStatement(jarPaths);
+ }
+
+ @Override
+ public DeleteJarStatement deleteJar(LiteralParseNode jarPath) {
+ return new ExecutableDeleteJarStatement(jarPath);
+ }
+
+ @Override
+ public ListJarsStatement listJars() {
+ return new ExecutableListJarsStatement();
+ }
+
+
@Override
public DropSequenceStatement dropSequence(TableName tableName, boolean ifExists, int bindCount){
return new ExecutableDropSequenceStatement(tableName, ifExists, bindCount);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/f006df54/phoenix-core/src/main/java/org/apache/phoenix/parse/AddJarsStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/AddJarsStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/AddJarsStatement.java
new file mode 100644
index 0000000..b1eeea6
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/AddJarsStatement.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.parse;
+
+import java.util.List;
+
+public class AddJarsStatement extends MutableStatement {
+
+ List<LiteralParseNode> jarPaths;
+
+ public AddJarsStatement(List<LiteralParseNode> jarPaths) {
+ this.jarPaths = jarPaths;
+ }
+
+ @Override
+ public int getBindCount() {
+ return 0;
+ }
+
+ public List<LiteralParseNode> getJarPaths() {
+ return jarPaths;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/f006df54/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java
new file mode 100644
index 0000000..7ccdc72
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/DeleteJarStatement.java
@@ -0,0 +1,19 @@
+package org.apache.phoenix.parse;
+
+public class DeleteJarStatement extends MutableStatement {
+
+ private LiteralParseNode jarPath;
+
+ public DeleteJarStatement(LiteralParseNode jarPath) {
+ this.jarPath = jarPath;
+ }
+
+ @Override
+ public int getBindCount() {
+ return 0;
+ }
+
+ public LiteralParseNode getJarPath() {
+ return jarPath;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/f006df54/phoenix-core/src/main/java/org/apache/phoenix/parse/ListJarsStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ListJarsStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ListJarsStatement.java
new file mode 100644
index 0000000..e9821fb
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ListJarsStatement.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.parse;
+
+import org.apache.phoenix.jdbc.PhoenixStatement.Operation;
+
+public class ListJarsStatement implements BindableStatement {
+
+ @Override
+ public int getBindCount() {
+ return 0;
+ }
+
+ @Override
+ public Operation getOperation() {
+ return Operation.QUERY;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/f006df54/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
index 49b14c6..cd239ac 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
@@ -301,6 +301,18 @@ public class ParseNodeFactory {
return new CreateFunctionStatement(functionInfo, temporary, isReplace);
}
+ public AddJarsStatement addJars(List<LiteralParseNode> jarPaths) {
+ return new AddJarsStatement(jarPaths);
+ }
+
+ public ListJarsStatement listJars() {
+ return new ListJarsStatement();
+ }
+
+ public DeleteJarStatement deleteJar(LiteralParseNode jarPath) {
+ return new DeleteJarStatement(jarPath);
+ }
+
public DropFunctionStatement dropFunction(String functionName, boolean ifExists) {
return new DropFunctionStatement(functionName, ifExists);
}
[21/50] [abbrv] phoenix git commit: PHOENIX-2099 Backward
Compatibility - Concurrent modification error on connect
Posted by ma...@apache.org.
PHOENIX-2099 Backward Compatibility - Concurrent modification error on connect
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/39afa9f1
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/39afa9f1
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/39afa9f1
Branch: refs/heads/calcite
Commit: 39afa9f18cad132a8a5c49b0e2e31671c85a3c7e
Parents: 997de5e
Author: Samarth <sa...@salesforce.com>
Authored: Fri Jul 10 11:04:44 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Fri Jul 10 11:04:44 2015 -0700
----------------------------------------------------------------------
.../coprocessor/MetaDataEndpointImpl.java | 24 +-
.../query/ConnectionQueryServicesImpl.java | 8 +-
.../org/apache/phoenix/util/UpgradeUtil.java | 416 ++++++++++---------
phoenix-protocol/src/main/PTable.proto | 1 +
4 files changed, 237 insertions(+), 212 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/39afa9f1/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index f786768..399d56e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -39,7 +39,6 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_ARRAY_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_CONSTANT_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_VIEW_REFERENCED_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.JAR_PATH_BYTES;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.KEY_SEQ_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.LINK_TYPE_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MAX_VALUE_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MIN_VALUE_BYTES;
@@ -1567,12 +1566,6 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
// We said to drop a table, but found a view or visa versa
if (type != expectedType) { return new MetaDataMutationResult(MutationCode.TABLE_NOT_FOUND,
EnvironmentEdgeManager.currentTimeMillis(), null); }
- if (table.getBaseColumnCount() == 0) {
- // If the base column count hasn't been set, then it means that the upgrade
- // to 4.5.0 is in progress. Have the client retry the mutation operation.
- return new MetaDataMutationResult(MutationCode.CONCURRENT_TABLE_MUTATION,
- EnvironmentEdgeManager.currentTimeMillis(), table);
- }
}
result = mutator.updateMutation(table, rowKeyMetaData, tableMetadata, region,
invalidateList, locks, clientTimeStamp);
@@ -1658,7 +1651,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
// if there is already a view column with the same name as the base table column we are trying to add
- if (existingViewColumn!=null) {
+ if (existingViewColumn != null) {
List<Cell> dataTypes = viewColumnDefinitionPut
.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.DATA_TYPE_BYTES);
@@ -1684,7 +1677,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
}
// if there is an existing view column that matches the column being added to the base table and if the column being added has a null
- // scale or maxLength, we need to explicity do a put to set the scale or maxLength to null (in case the view column has the scale or
+ // scale or maxLength, we need to explicitly do a put to set the scale or maxLength to null (in case the view column has the scale or
// max length set)
List<Cell> columnSizes = viewColumnDefinitionPut.get(
PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
@@ -1714,7 +1707,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
}
else {
- // if we are adding a column that already exists in the view, no need to updates the base table or view table column count
+ // if we are adding a column that already exists in the view, no need to update the base table or view table column count
numColsAddedToView++;
}
@@ -1914,9 +1907,14 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
if (type == PTableType.TABLE || type == PTableType.SYSTEM) {
TableViewFinderResult childViewsResult = findChildViews(region, tenantId, table, PHYSICAL_TABLE_BYTES);
if (childViewsResult.hasViews()) {
- // Adding a column is not allowed if the meta-data for child view/s spans over
- // more than one region (since the changes cannot be done in a transactional fashion)
- if (!childViewsResult.allViewsInSingleRegion()) {
+ /*
+ * Adding a column is not allowed if the meta-data for child view/s spans over
+ * more than one region (since the changes cannot be made in a transactional fashion)
+ * A base column count of 0 means that the metadata hasn't been upgraded yet or
+ * the upgrade is currently in progress. If that is the case, disallow adding columns
+ * for tables with views.
+ */
+ if (!childViewsResult.allViewsInSingleRegion() || table.getBaseColumnCount() == 0) {
return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION,
EnvironmentEdgeManager.currentTimeMillis(), null);
} else {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/39afa9f1/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 a9f455a..9cd32e8 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
@@ -1826,7 +1826,10 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
return result;
}
-
+
+ /**
+ * This closes the passed connection.
+ */
private PhoenixConnection addColumn(PhoenixConnection oldMetaConnection, String tableName, long timestamp, String columns, boolean addIfNotExists) throws SQLException {
Properties props = new Properties(oldMetaConnection.getClientInfo());
props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(timestamp));
@@ -1956,7 +1959,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
columnsToAdd = PhoenixDatabaseMetaData.BASE_COLUMN_COUNT + " "
+ PInteger.INSTANCE.getSqlTypeName();
try {
- addColumn(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG,
+ metaConnection = addColumn(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG,
MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP, columnsToAdd, false);
upgradeTo4_5_0(metaConnection);
} catch (ColumnAlreadyExistsException ignored) {
@@ -1965,6 +1968,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
* BASE_COLUMN_COUNT is already part of the meta-data schema as the signal that
* the server side upgrade has finished or is in progress.
*/
+ logger.debug("No need to run 4.5 upgrade");
}
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/39afa9f1/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
index 8d574ce..c829799 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
@@ -443,216 +443,238 @@ public class UpgradeUtil {
buf, keyValue.getValueOffset(), keyValue.getValueLength());
}
- public static void upgradeTo4_5_0(PhoenixConnection metaConnection) throws SQLException {
- String getBaseTableAndViews = "SELECT "
- + COLUMN_FAMILY + " AS BASE_PHYSICAL_TABLE, "
- + TENANT_ID + ", "
- + TABLE_SCHEM + " AS VIEW_SCHEMA, "
- + TABLE_NAME + " AS VIEW_NAME "
- + "FROM " + SYSTEM_CATALOG_NAME
- + " WHERE " + COLUMN_FAMILY + " IS NOT NULL " // column_family column points to the physical table name.
- + " AND " + COLUMN_NAME + " IS NULL "
- + " AND " + LINK_TYPE + " = ? ";
- // Build a map of base table name -> list of views on the table.
- Map<String, List<ViewKey>> parentTableViewsMap = new HashMap<>();
- try (PreparedStatement stmt = metaConnection.prepareStatement(getBaseTableAndViews)) {
- // Get back view rows that have links back to the base physical table. This takes care
- // of cases when we have a hierarchy of views too.
- stmt.setByte(1, LinkType.PHYSICAL_TABLE.getSerializedValue());
- try (ResultSet rs = stmt.executeQuery()) {
- while (rs.next()) {
- // this is actually SCHEMANAME.TABLENAME
- String parentTable = rs.getString("BASE_PHYSICAL_TABLE");
- String tenantId = rs.getString(TENANT_ID);
- String viewSchema = rs.getString("VIEW_SCHEMA");
- String viewName = rs.getString("VIEW_NAME");
- List<ViewKey> viewKeysList = parentTableViewsMap.get(parentTable);
- if (viewKeysList == null) {
- viewKeysList = new ArrayList<>();
- parentTableViewsMap.put(parentTable, viewKeysList);
+ /**
+ * Upgrade the metadata in the catalog table to enable adding columns to tables with views
+ * @param oldMetaConnection caller should take care of closing the passed connection appropriately
+ * @throws SQLException
+ */
+ public static void upgradeTo4_5_0(PhoenixConnection oldMetaConnection) throws SQLException {
+ PhoenixConnection metaConnection = null;
+ try {
+ // Need to use own connection without any SCN to be able to read all data from SYSTEM.CATALOG
+ metaConnection = new PhoenixConnection(oldMetaConnection);
+ logger.info("Upgrading metadata to support adding columns to tables with views");
+ String getBaseTableAndViews = "SELECT "
+ + COLUMN_FAMILY + " AS BASE_PHYSICAL_TABLE, "
+ + TENANT_ID + ", "
+ + TABLE_SCHEM + " AS VIEW_SCHEMA, "
+ + TABLE_NAME + " AS VIEW_NAME "
+ + "FROM " + SYSTEM_CATALOG_NAME
+ + " WHERE " + COLUMN_FAMILY + " IS NOT NULL " // column_family column points to the physical table name.
+ + " AND " + COLUMN_NAME + " IS NULL "
+ + " AND " + LINK_TYPE + " = ? ";
+ // Build a map of base table name -> list of views on the table.
+ Map<String, List<ViewKey>> parentTableViewsMap = new HashMap<>();
+ try (PreparedStatement stmt = metaConnection.prepareStatement(getBaseTableAndViews)) {
+ // Get back view rows that have links back to the base physical table. This takes care
+ // of cases when we have a hierarchy of views too.
+ stmt.setByte(1, LinkType.PHYSICAL_TABLE.getSerializedValue());
+ try (ResultSet rs = stmt.executeQuery()) {
+ while (rs.next()) {
+ // this is actually SCHEMANAME.TABLENAME
+ String parentTable = rs.getString("BASE_PHYSICAL_TABLE");
+ String tenantId = rs.getString(TENANT_ID);
+ String viewSchema = rs.getString("VIEW_SCHEMA");
+ String viewName = rs.getString("VIEW_NAME");
+ List<ViewKey> viewKeysList = parentTableViewsMap.get(parentTable);
+ if (viewKeysList == null) {
+ viewKeysList = new ArrayList<>();
+ parentTableViewsMap.put(parentTable, viewKeysList);
+ }
+ viewKeysList.add(new ViewKey(tenantId, viewSchema, viewName));
}
- viewKeysList.add(new ViewKey(tenantId, viewSchema, viewName));
}
}
- }
-
- for (Entry<String, List<ViewKey>> entry : parentTableViewsMap.entrySet()) {
- // Fetch column information for the base physical table
- String physicalTable = entry.getKey();
- String baseTableSchemaName = SchemaUtil.getSchemaNameFromFullName(physicalTable).equals(StringUtil.EMPTY_STRING) ? null : SchemaUtil.getSchemaNameFromFullName(physicalTable);
- String baseTableName = SchemaUtil.getTableNameFromFullName(physicalTable);
- List<ColumnDetails> basePhysicalTableColumns = new ArrayList<>();
-
- // Columns fetched in order of ordinal position
- String fetchColumnInfoForBasePhysicalTable = "SELECT " +
- COLUMN_NAME + "," +
- COLUMN_FAMILY + "," +
- DATA_TYPE + "," +
- COLUMN_SIZE + "," +
- DECIMAL_DIGITS + "," +
- ORDINAL_POSITION + "," +
- SORT_ORDER + "," +
- ARRAY_SIZE + " " +
- "FROM SYSTEM.CATALOG " +
- "WHERE " +
- "TABLE_SCHEM %s " +
- "AND TABLE_NAME = ? " +
- "AND COLUMN_NAME IS NOT NULL " +
- "ORDER BY " +
- ORDINAL_POSITION;
-
- PreparedStatement stmt = null;
- if (baseTableSchemaName == null) {
- fetchColumnInfoForBasePhysicalTable =
- String.format(fetchColumnInfoForBasePhysicalTable, "IS NULL ");
- stmt = metaConnection.prepareStatement(fetchColumnInfoForBasePhysicalTable);
- stmt.setString(1, baseTableName);
- } else {
- fetchColumnInfoForBasePhysicalTable =
- String.format(fetchColumnInfoForBasePhysicalTable, " = ? ");
- stmt = metaConnection.prepareStatement(fetchColumnInfoForBasePhysicalTable);
- stmt.setString(1, baseTableSchemaName);
- stmt.setString(2, baseTableName);
- }
+ boolean clearCache = false;
+ for (Entry<String, List<ViewKey>> entry : parentTableViewsMap.entrySet()) {
+ // Fetch column information for the base physical table
+ String physicalTable = entry.getKey();
+ String baseTableSchemaName = SchemaUtil.getSchemaNameFromFullName(physicalTable).equals(StringUtil.EMPTY_STRING) ? null : SchemaUtil.getSchemaNameFromFullName(physicalTable);
+ String baseTableName = SchemaUtil.getTableNameFromFullName(physicalTable);
+ List<ColumnDetails> basePhysicalTableColumns = new ArrayList<>();
+
+ // Columns fetched in order of ordinal position
+ String fetchColumnInfoForBasePhysicalTable = "SELECT " +
+ COLUMN_NAME + "," +
+ COLUMN_FAMILY + "," +
+ DATA_TYPE + "," +
+ COLUMN_SIZE + "," +
+ DECIMAL_DIGITS + "," +
+ ORDINAL_POSITION + "," +
+ SORT_ORDER + "," +
+ ARRAY_SIZE + " " +
+ "FROM SYSTEM.CATALOG " +
+ "WHERE " +
+ "TABLE_SCHEM %s " +
+ "AND TABLE_NAME = ? " +
+ "AND COLUMN_NAME IS NOT NULL " +
+ "ORDER BY " +
+ ORDINAL_POSITION;
+
+ PreparedStatement stmt = null;
+ if (baseTableSchemaName == null) {
+ fetchColumnInfoForBasePhysicalTable =
+ String.format(fetchColumnInfoForBasePhysicalTable, "IS NULL ");
+ stmt = metaConnection.prepareStatement(fetchColumnInfoForBasePhysicalTable);
+ stmt.setString(1, baseTableName);
+ } else {
+ fetchColumnInfoForBasePhysicalTable =
+ String.format(fetchColumnInfoForBasePhysicalTable, " = ? ");
+ stmt = metaConnection.prepareStatement(fetchColumnInfoForBasePhysicalTable);
+ stmt.setString(1, baseTableSchemaName);
+ stmt.setString(2, baseTableName);
+ }
- try (ResultSet rs = stmt.executeQuery()) {
- while (rs.next()) {
- basePhysicalTableColumns.add(new ColumnDetails(rs.getString(COLUMN_FAMILY), rs
- .getString(COLUMN_NAME), rs.getInt(ORDINAL_POSITION), rs
- .getInt(DATA_TYPE), rs.getInt(COLUMN_SIZE), rs.getInt(DECIMAL_DIGITS),
- rs.getInt(SORT_ORDER), rs.getInt(ARRAY_SIZE)));
+ try (ResultSet rs = stmt.executeQuery()) {
+ while (rs.next()) {
+ basePhysicalTableColumns.add(new ColumnDetails(rs.getString(COLUMN_FAMILY), rs
+ .getString(COLUMN_NAME), rs.getInt(ORDINAL_POSITION), rs
+ .getInt(DATA_TYPE), rs.getInt(COLUMN_SIZE), rs.getInt(DECIMAL_DIGITS),
+ rs.getInt(SORT_ORDER), rs.getInt(ARRAY_SIZE)));
+ }
}
- }
-
- // Fetch column information for all the views on the base physical table ordered by ordinal position.
- List<ViewKey> viewKeys = entry.getValue();
- StringBuilder sb = new StringBuilder();
- sb.append("SELECT " +
- TENANT_ID + "," +
- TABLE_SCHEM + "," +
- TABLE_NAME + "," +
- COLUMN_NAME + "," +
- COLUMN_FAMILY + "," +
- DATA_TYPE + "," +
- COLUMN_SIZE + "," +
- DECIMAL_DIGITS + "," +
- ORDINAL_POSITION + "," +
- SORT_ORDER + "," +
- ARRAY_SIZE + " " +
- "FROM SYSTEM.CATALOG " +
- "WHERE " +
- COLUMN_NAME + " IS NOT NULL " +
- "AND " +
- ORDINAL_POSITION + " <= ? " + // fetch only those columns that would impact setting of base column count
- "AND " +
- "(" + TENANT_ID+ ", " + TABLE_SCHEM + ", " + TABLE_NAME + ") IN (");
-
- int numViews = viewKeys.size();
- for (int i = 0; i < numViews; i++) {
- sb.append(" (?, ?, ?) ");
- if (i < numViews - 1) {
- sb.append(", ");
+
+ // Fetch column information for all the views on the base physical table ordered by ordinal position.
+ List<ViewKey> viewKeys = entry.getValue();
+ StringBuilder sb = new StringBuilder();
+ sb.append("SELECT " +
+ TENANT_ID + "," +
+ TABLE_SCHEM + "," +
+ TABLE_NAME + "," +
+ COLUMN_NAME + "," +
+ COLUMN_FAMILY + "," +
+ DATA_TYPE + "," +
+ COLUMN_SIZE + "," +
+ DECIMAL_DIGITS + "," +
+ ORDINAL_POSITION + "," +
+ SORT_ORDER + "," +
+ ARRAY_SIZE + " " +
+ "FROM SYSTEM.CATALOG " +
+ "WHERE " +
+ COLUMN_NAME + " IS NOT NULL " +
+ "AND " +
+ ORDINAL_POSITION + " <= ? " + // fetch only those columns that would impact setting of base column count
+ "AND " +
+ "(" + TENANT_ID+ ", " + TABLE_SCHEM + ", " + TABLE_NAME + ") IN (");
+
+ int numViews = viewKeys.size();
+ for (int i = 0; i < numViews; i++) {
+ sb.append(" (?, ?, ?) ");
+ if (i < numViews - 1) {
+ sb.append(", ");
+ }
}
- }
- sb.append(" ) ");
- sb.append(" GROUP BY " +
- TENANT_ID + "," +
- TABLE_SCHEM + "," +
- TABLE_NAME + "," +
- COLUMN_NAME + "," +
- COLUMN_FAMILY + "," +
- DATA_TYPE + "," +
- COLUMN_SIZE + "," +
- DECIMAL_DIGITS + "," +
- ORDINAL_POSITION + "," +
- SORT_ORDER + "," +
- ARRAY_SIZE + " " +
- "ORDER BY " +
- TENANT_ID + "," + TABLE_SCHEM + ", " + TABLE_NAME + ", " + ORDINAL_POSITION);
- String fetchViewColumnsSql = sb.toString();
- stmt = metaConnection.prepareStatement(fetchViewColumnsSql);
- int numColsInBaseTable = basePhysicalTableColumns.size();
- stmt.setInt(1, numColsInBaseTable);
- int paramIndex = 1;
- stmt.setInt(paramIndex++, numColsInBaseTable);
- for (ViewKey view : viewKeys) {
- stmt.setString(paramIndex++, view.tenantId);
- stmt.setString(paramIndex++, view.schema);
- stmt.setString(paramIndex++, view.name);
- }
- String currentTenantId = null;
- String currentViewSchema = null;
- String currentViewName = null;
- try (ResultSet rs = stmt.executeQuery()) {
- int numBaseTableColsMatched = 0;
- boolean ignore = false;
- boolean baseColumnCountUpserted = false;
- while (rs.next()) {
- String viewTenantId = rs.getString(TENANT_ID);
- String viewSchema = rs.getString(TABLE_SCHEM);
- String viewName = rs.getString(TABLE_NAME);
- if (!(Objects.equal(viewTenantId, currentTenantId) && Objects.equal(viewSchema, currentViewSchema) && Objects.equal(viewName, currentViewName))) {
- // We are about to iterate through columns of a different view. Check whether base column count was upserted.
- // If it wasn't then it is likely the case that a column inherited from the base table was dropped from view.
- if (currentViewName != null && !baseColumnCountUpserted && numBaseTableColsMatched < numColsInBaseTable) {
- upsertBaseColumnCountInHeaderRow(metaConnection, currentTenantId, currentViewSchema, currentViewName, DIVERGED_VIEW_BASE_COLUMN_COUNT);
+ sb.append(" ) ");
+ sb.append(" GROUP BY " +
+ TENANT_ID + "," +
+ TABLE_SCHEM + "," +
+ TABLE_NAME + "," +
+ COLUMN_NAME + "," +
+ COLUMN_FAMILY + "," +
+ DATA_TYPE + "," +
+ COLUMN_SIZE + "," +
+ DECIMAL_DIGITS + "," +
+ ORDINAL_POSITION + "," +
+ SORT_ORDER + "," +
+ ARRAY_SIZE + " " +
+ "ORDER BY " +
+ TENANT_ID + "," + TABLE_SCHEM + ", " + TABLE_NAME + ", " + ORDINAL_POSITION);
+ String fetchViewColumnsSql = sb.toString();
+ stmt = metaConnection.prepareStatement(fetchViewColumnsSql);
+ int numColsInBaseTable = basePhysicalTableColumns.size();
+ stmt.setInt(1, numColsInBaseTable);
+ int paramIndex = 1;
+ stmt.setInt(paramIndex++, numColsInBaseTable);
+ for (ViewKey view : viewKeys) {
+ stmt.setString(paramIndex++, view.tenantId);
+ stmt.setString(paramIndex++, view.schema);
+ stmt.setString(paramIndex++, view.name);
+ }
+ String currentTenantId = null;
+ String currentViewSchema = null;
+ String currentViewName = null;
+ try (ResultSet rs = stmt.executeQuery()) {
+ int numBaseTableColsMatched = 0;
+ boolean ignore = false;
+ boolean baseColumnCountUpserted = false;
+ while (rs.next()) {
+ String viewTenantId = rs.getString(TENANT_ID);
+ String viewSchema = rs.getString(TABLE_SCHEM);
+ String viewName = rs.getString(TABLE_NAME);
+ if (!(Objects.equal(viewTenantId, currentTenantId) && Objects.equal(viewSchema, currentViewSchema) && Objects.equal(viewName, currentViewName))) {
+ // We are about to iterate through columns of a different view. Check whether base column count was upserted.
+ // If it wasn't then it is likely the case that a column inherited from the base table was dropped from view.
+ if (currentViewName != null && !baseColumnCountUpserted && numBaseTableColsMatched < numColsInBaseTable) {
+ upsertBaseColumnCountInHeaderRow(metaConnection, currentTenantId, currentViewSchema, currentViewName, DIVERGED_VIEW_BASE_COLUMN_COUNT);
+ clearCache = true;
+ }
+ // reset the values as we are now going to iterate over columns of a new view.
+ numBaseTableColsMatched = 0;
+ currentTenantId = viewTenantId;
+ currentViewSchema = viewSchema;
+ currentViewName = viewName;
+ ignore = false;
+ baseColumnCountUpserted = false;
}
- // reset the values as we are now going to iterate over columns of a new view.
- numBaseTableColsMatched = 0;
- currentTenantId = viewTenantId;
- currentViewSchema = viewSchema;
- currentViewName = viewName;
- ignore = false;
- baseColumnCountUpserted = false;
- }
- if (!ignore) {
- /*
- * Iterate over all the columns of the base physical table and the columns of the view. Compare the
- * two till one of the following happens:
- *
- * 1) We run into a view column which is different from column in the base physical table.
- * This means that the view has divorced itself from the base physical table. In such a case
- * we will set a special value for the base column count. That special value will also be used
- * on the server side to filter out the divorced view so that meta-data changes on the base
- * physical table are not propagated to it.
- *
- * 2) Every physical table column is present in the view. In that case we set the base column count
- * as the number of columns in the base physical table. At that point we ignore rest of the columns
- * of the view.
- *
- */
- ColumnDetails baseTableColumn = basePhysicalTableColumns.get(numBaseTableColsMatched);
- String columName = rs.getString(COLUMN_NAME);
- String columnFamily = rs.getString(COLUMN_FAMILY);
- int ordinalPos = rs.getInt(ORDINAL_POSITION);
- int dataType = rs.getInt(DATA_TYPE);
- int columnSize = rs.getInt(COLUMN_SIZE);
- int decimalDigits = rs.getInt(DECIMAL_DIGITS);
- int sortOrder = rs.getInt(SORT_ORDER);
- int arraySize = rs.getInt(ARRAY_SIZE);
- ColumnDetails viewColumn = new ColumnDetails(columnFamily, columName, ordinalPos, dataType, columnSize, decimalDigits, sortOrder, arraySize);
- if (baseTableColumn.equals(viewColumn)) {
- numBaseTableColsMatched++;
- if (numBaseTableColsMatched == numColsInBaseTable) {
- upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, numColsInBaseTable);
- // No need to ignore the rest of the columns of the view here since the
- // query retrieved only those columns that had ordinal position <= numColsInBaseTable
+ if (!ignore) {
+ /*
+ * Iterate over all the columns of the base physical table and the columns of the view. Compare the
+ * two till one of the following happens:
+ *
+ * 1) We run into a view column which is different from column in the base physical table.
+ * This means that the view has divorced itself from the base physical table. In such a case
+ * we will set a special value for the base column count. That special value will also be used
+ * on the server side to filter out the divorced view so that meta-data changes on the base
+ * physical table are not propagated to it.
+ *
+ * 2) Every physical table column is present in the view. In that case we set the base column count
+ * as the number of columns in the base physical table. At that point we ignore rest of the columns
+ * of the view.
+ *
+ */
+ ColumnDetails baseTableColumn = basePhysicalTableColumns.get(numBaseTableColsMatched);
+ String columName = rs.getString(COLUMN_NAME);
+ String columnFamily = rs.getString(COLUMN_FAMILY);
+ int ordinalPos = rs.getInt(ORDINAL_POSITION);
+ int dataType = rs.getInt(DATA_TYPE);
+ int columnSize = rs.getInt(COLUMN_SIZE);
+ int decimalDigits = rs.getInt(DECIMAL_DIGITS);
+ int sortOrder = rs.getInt(SORT_ORDER);
+ int arraySize = rs.getInt(ARRAY_SIZE);
+ ColumnDetails viewColumn = new ColumnDetails(columnFamily, columName, ordinalPos, dataType, columnSize, decimalDigits, sortOrder, arraySize);
+ if (baseTableColumn.equals(viewColumn)) {
+ numBaseTableColsMatched++;
+ if (numBaseTableColsMatched == numColsInBaseTable) {
+ upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, numColsInBaseTable);
+ // No need to ignore the rest of the columns of the view here since the
+ // query retrieved only those columns that had ordinal position <= numColsInBaseTable
+ baseColumnCountUpserted = true;
+ clearCache = true;
+ }
+ } else {
+ // special value to denote that the view has divorced itself from the base physical table.
+ upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, DIVERGED_VIEW_BASE_COLUMN_COUNT);
baseColumnCountUpserted = true;
+ clearCache = true;
+ // ignore rest of the rows for the view.
+ ignore = true;
}
- } else {
- // special value to denote that the view has divorced itself from the base physical table.
- upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, DIVERGED_VIEW_BASE_COLUMN_COUNT);
- baseColumnCountUpserted = true;
- // ignore rest of the rows for the view.
- ignore = true;
}
}
}
+ // set base column count for the header row of the base table too. We use this information
+ // to figure out whether the upgrade is in progress or hasn't started.
+ upsertBaseColumnCountInHeaderRow(metaConnection, null, baseTableSchemaName, baseTableName, BASE_TABLE_BASE_COLUMN_COUNT);
+ metaConnection.commit();
+ }
+ // clear metadata cache on region servers to force loading of the latest metadata
+ if (clearCache) {
+ metaConnection.getQueryServices().clearCache();
+ }
+ } finally {
+ if (metaConnection != null) {
+ metaConnection.close();
}
- // set base column count for the header row of the base table too. We use this information
- // to figure out whether the upgrade is in progress or hasn't started.
- upsertBaseColumnCountInHeaderRow(metaConnection, null, baseTableSchemaName, baseTableName, BASE_TABLE_BASE_COLUMN_COUNT);
- metaConnection.commit();
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/39afa9f1/phoenix-protocol/src/main/PTable.proto
----------------------------------------------------------------------
diff --git a/phoenix-protocol/src/main/PTable.proto b/phoenix-protocol/src/main/PTable.proto
index 348631f..cbbbdd6 100644
--- a/phoenix-protocol/src/main/PTable.proto
+++ b/phoenix-protocol/src/main/PTable.proto
@@ -83,4 +83,5 @@ message PTable {
optional bytes indexType = 22;
optional int64 statsTimeStamp = 23;
optional bool storeNulls = 24;
+ optional int32 baseColumnCount = 25;
}
[40/50] [abbrv] phoenix git commit: PHOENIX-2117 Fix flapping
DataIngestIT
Posted by ma...@apache.org.
PHOENIX-2117 Fix flapping DataIngestIT
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/cf2bc551
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/cf2bc551
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/cf2bc551
Branch: refs/heads/calcite
Commit: cf2bc55175788603830ba8bc8b3eacc0998361c1
Parents: 9f09f1a
Author: Samarth <sa...@salesforce.com>
Authored: Tue Jul 14 17:40:29 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Tue Jul 14 17:40:46 2015 -0700
----------------------------------------------------------------------
phoenix-pherf/src/test/resources/datamodel/test_schema.sql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/cf2bc551/phoenix-pherf/src/test/resources/datamodel/test_schema.sql
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/test/resources/datamodel/test_schema.sql b/phoenix-pherf/src/test/resources/datamodel/test_schema.sql
index 162d288..4e6b9d4 100644
--- a/phoenix-pherf/src/test/resources/datamodel/test_schema.sql
+++ b/phoenix-pherf/src/test/resources/datamodel/test_schema.sql
@@ -29,4 +29,4 @@ CREATE TABLE IF NOT EXISTS PHERF.TEST_TABLE (
PARENT_ID,
CREATED_DATE DESC
)
-) VERSIONS=1,MULTI_TENANT=true,SALT_BUCKETS=16
+) VERSIONS=1,MULTI_TENANT=true
[07/50] [abbrv] phoenix git commit: PHOENIX-2074 StackOverflowError
for hash join with round robin
Posted by ma...@apache.org.
PHOENIX-2074 StackOverflowError for hash join with round robin
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/d0c8f9db
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/d0c8f9db
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/d0c8f9db
Branch: refs/heads/calcite
Commit: d0c8f9dbd15460c023d50c8b8fd9334fb18c05dc
Parents: 39c982f
Author: maryannxue <we...@intel.com>
Authored: Tue Jul 7 13:27:49 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Tue Jul 7 13:27:49 2015 -0400
----------------------------------------------------------------------
.../iterate/RoundRobinResultIteratorIT.java | 80 ++++++++++++++++++++
.../iterate/RoundRobinResultIterator.java | 2 +-
2 files changed, 81 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/d0c8f9db/phoenix-core/src/it/java/org/apache/phoenix/iterate/RoundRobinResultIteratorIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/iterate/RoundRobinResultIteratorIT.java b/phoenix-core/src/it/java/org/apache/phoenix/iterate/RoundRobinResultIteratorIT.java
index 6a9b3d4..224ed95 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/iterate/RoundRobinResultIteratorIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/iterate/RoundRobinResultIteratorIT.java
@@ -17,6 +17,7 @@
*/
package org.apache.phoenix.iterate;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
@@ -30,6 +31,7 @@ import java.sql.Statement;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -43,6 +45,7 @@ import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.jdbc.PhoenixResultSet;
import org.apache.phoenix.query.ConnectionQueryServices;
import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.ReadOnlyProps;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -301,6 +304,83 @@ public class RoundRobinResultIteratorIT extends BaseHBaseManagedTimeIT {
assertEquals("Number of rows retrieved didnt match for tableB", insertedRowsB, rowsB);
assertEquals("Number of rows retrieved didn't match for tableC", insertedRowsC, rowsC);
}
+
+ @Test
+ public void testBug2074() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.createStatement().execute("CREATE TABLE EVENTS"
+ + " (id VARCHAR(10) PRIMARY KEY, "
+ + " article VARCHAR(10), "
+ + " misc VARCHAR(10))");
+
+ PreparedStatement upsertStmt = conn.prepareStatement(
+ "upsert into EVENTS(id, article, misc) " + "values (?, ?, ?)");
+ upsertStmt.setString(1, "001");
+ upsertStmt.setString(2, "A");
+ upsertStmt.setString(3, "W");
+ upsertStmt.execute();
+ upsertStmt.setString(1, "002");
+ upsertStmt.setString(2, "B");
+ upsertStmt.setString(3, "X");
+ upsertStmt.execute();
+ upsertStmt.setString(1, "003");
+ upsertStmt.setString(2, "C");
+ upsertStmt.setString(3, "Y");
+ upsertStmt.execute();
+ upsertStmt.setString(1, "004");
+ upsertStmt.setString(2, "D");
+ upsertStmt.setString(3, "Z");
+ upsertStmt.execute();
+ conn.commit();
+
+ conn.createStatement().execute("CREATE TABLE MAPPING"
+ + " (id VARCHAR(10) PRIMARY KEY, "
+ + " article VARCHAR(10), "
+ + " category VARCHAR(10))");
+
+ upsertStmt = conn.prepareStatement(
+ "upsert into MAPPING(id, article, category) " + "values (?, ?, ?)");
+ upsertStmt.setString(1, "002");
+ upsertStmt.setString(2, "A");
+ upsertStmt.setString(3, "X");
+ upsertStmt.execute();
+ upsertStmt.setString(1, "003");
+ upsertStmt.setString(2, "B");
+ upsertStmt.setString(3, "Y");
+ upsertStmt.execute();
+ upsertStmt.setString(1, "004");
+ upsertStmt.setString(2, "C");
+ upsertStmt.setString(3, "Z");
+ upsertStmt.execute();
+ upsertStmt.setString(1, "005");
+ upsertStmt.setString(2, "E");
+ upsertStmt.setString(3, "Z");
+ upsertStmt.execute();
+ upsertStmt.setString(1, "006");
+ upsertStmt.setString(2, "C");
+ upsertStmt.setString(3, "Z");
+ upsertStmt.execute();
+ upsertStmt.setString(1, "007");
+ upsertStmt.setString(2, "C");
+ upsertStmt.setString(3, "Z");
+ upsertStmt.execute();
+ conn.commit();
+
+ // No leading part of PK
+ String query = "select count(MAPPING.article) as cnt,MAPPING.category from EVENTS"
+ + " join MAPPING on MAPPING.article = EVENTS.article"
+ + " group by category order by cnt";
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setFetchSize(3);
+ ResultSet rs = statement.executeQuery();
+ while(rs.next());
+
+ } finally {
+ conn.close();
+ }
+ }
private static ResultIterator getResultIterator(ResultSet rs) throws SQLException {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/d0c8f9db/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java
index 92ac570..5624f5f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/RoundRobinResultIterator.java
@@ -240,7 +240,7 @@ public class RoundRobinResultIterator implements ResultIterator {
for (Future<Tuple> future : futures) {
Tuple tuple = future.get();
if (tuple != null) {
- results.add(new RoundRobinIterator(openIterators.get(i), tuple));
+ results.add(new RoundRobinIterator(openIterators.get(i).delegate, tuple));
} else {
// Underlying scanner is exhausted. So close it.
openIterators.get(i).close();
[39/50] [abbrv] phoenix git commit: PHOENIX-2111 Race condition on
creation of new view and adding of column to base table
Posted by ma...@apache.org.
PHOENIX-2111 Race condition on creation of new view and adding of column to base table
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/9f09f1a5
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/9f09f1a5
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/9f09f1a5
Branch: refs/heads/calcite
Commit: 9f09f1a5ddce38c256c647ca7cd80617259e35ea
Parents: 4b99c63
Author: Samarth <sa...@salesforce.com>
Authored: Tue Jul 14 17:24:01 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Tue Jul 14 17:24:01 2015 -0700
----------------------------------------------------------------------
.../coprocessor/MetaDataEndpointImpl.java | 239 ++--
.../coprocessor/generated/MetaDataProtos.java | 1243 +++++++++++++++++-
.../query/ConnectionQueryServicesImpl.java | 75 +-
.../apache/phoenix/schema/MetaDataClient.java | 12 +-
.../org/apache/phoenix/util/MetaDataUtil.java | 14 +
.../org/apache/phoenix/util/PhoenixRuntime.java | 4 -
.../org/apache/phoenix/util/UpgradeUtil.java | 4 +-
phoenix-protocol/src/main/MetaDataService.proto | 14 +-
8 files changed, 1414 insertions(+), 191 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f09f1a5/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index dcfe61d..5396a69 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -1068,6 +1068,50 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
return null;
}
+ /**
+ *
+ * @return null if the physical table row information is not present.
+ *
+ */
+ private static Mutation getPhysicalTableForView(List<Mutation> tableMetadata, byte[][] parentSchemaTableNames) {
+ int size = tableMetadata.size();
+ byte[][] rowKeyMetaData = new byte[3][];
+ MetaDataUtil.getTenantIdAndSchemaAndTableName(tableMetadata, rowKeyMetaData);
+ Mutation physicalTableRow = null;
+ boolean physicalTableLinkFound = false;
+ if (size >= 2) {
+ int i = size - 1;
+ while (i >= 1) {
+ Mutation m = tableMetadata.get(i);
+ if (m instanceof Put) {
+ LinkType linkType = MetaDataUtil.getLinkType(m);
+ if (linkType == LinkType.PHYSICAL_TABLE) {
+ physicalTableRow = m;
+ physicalTableLinkFound = true;
+ break;
+ }
+ }
+ i--;
+ }
+ }
+ if (!physicalTableLinkFound) {
+ parentSchemaTableNames[0] = null;
+ parentSchemaTableNames[1] = null;
+ return null;
+ }
+ rowKeyMetaData = new byte[5][];
+ getVarChars(physicalTableRow.getRow(), 5, rowKeyMetaData);
+ byte[] colBytes = rowKeyMetaData[PhoenixDatabaseMetaData.COLUMN_NAME_INDEX];
+ byte[] famBytes = rowKeyMetaData[PhoenixDatabaseMetaData.FAMILY_NAME_INDEX];
+ if ((colBytes == null || colBytes.length == 0) && (famBytes != null && famBytes.length > 0)) {
+ byte[] sName = SchemaUtil.getSchemaNameFromFullName(famBytes).getBytes();
+ byte[] tName = SchemaUtil.getTableNameFromFullName(famBytes).getBytes();
+ parentSchemaTableNames[0] = sName;
+ parentSchemaTableNames[1] = tName;
+ }
+ return physicalTableRow;
+ }
+
@Override
public void createTable(RpcController controller, CreateTableRequest request,
RpcCallback<MetaDataResponse> done) {
@@ -1075,66 +1119,101 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
byte[][] rowKeyMetaData = new byte[3][];
byte[] schemaName = null;
byte[] tableName = null;
-
try {
List<Mutation> tableMetadata = ProtobufUtil.getMutations(request);
MetaDataUtil.getTenantIdAndSchemaAndTableName(tableMetadata, rowKeyMetaData);
byte[] tenantIdBytes = rowKeyMetaData[PhoenixDatabaseMetaData.TENANT_ID_INDEX];
schemaName = rowKeyMetaData[PhoenixDatabaseMetaData.SCHEMA_NAME_INDEX];
tableName = rowKeyMetaData[PhoenixDatabaseMetaData.TABLE_NAME_INDEX];
- byte[] parentTableName = MetaDataUtil.getParentTableName(tableMetadata);
- byte[] lockTableName = parentTableName == null ? tableName : parentTableName;
- byte[] lockKey = SchemaUtil.getTableKey(tenantIdBytes, schemaName, lockTableName);
- byte[] key =
- parentTableName == null ? lockKey : SchemaUtil.getTableKey(tenantIdBytes,
- schemaName, tableName);
- byte[] parentKey = parentTableName == null ? null : lockKey;
- Region region = env.getRegion();
- MetaDataMutationResult result = checkTableKeyInRegion(lockKey, region);
- if (result != null) {
- done.run(MetaDataMutationResult.toProto(result));
- return;
+ byte[] parentSchemaName = null;
+ byte[] parentTableName = null;
+ PTableType tableType = MetaDataUtil.getTableType(tableMetadata, GenericKeyValueBuilder.INSTANCE, new ImmutableBytesWritable());
+ byte[] parentTableKey = null;
+ Mutation viewPhysicalTableRow = null;
+ if (tableType == PTableType.VIEW) {
+ byte[][] parentSchemaTableNames = new byte[2][];
+ /*
+ * For a view, we lock the base physical table row. For a mapped view, there is
+ * no link present to the physical table. So the viewPhysicalTableRow is null
+ * in that case.
+ */
+ viewPhysicalTableRow = getPhysicalTableForView(tableMetadata, parentSchemaTableNames);
+ parentSchemaName = parentSchemaTableNames[0];
+ parentTableName = parentSchemaTableNames[1];
+ if (parentTableName != null) {
+ parentTableKey = SchemaUtil.getTableKey(ByteUtil.EMPTY_BYTE_ARRAY, parentSchemaName, parentTableName);
+ }
+ } else if (tableType == PTableType.INDEX) {
+ parentSchemaName = schemaName;
+ /*
+ * For an index we lock the parent table's row which could be a physical table or a view.
+ * If the parent table is a physical table, then the tenantIdBytes is empty because
+ * we allow creating an index with a tenant connection only if the parent table is a view.
+ */
+ parentTableName = MetaDataUtil.getParentTableName(tableMetadata);
+ parentTableKey = SchemaUtil.getTableKey(tenantIdBytes, parentSchemaName, parentTableName);
}
+
+ Region region = env.getRegion();
List<RowLock> locks = Lists.newArrayList();
- long clientTimeStamp = MetaDataUtil.getClientTimeStamp(tableMetadata);
+ // Place a lock using key for the table to be created
+ byte[] tableKey = SchemaUtil.getTableKey(tenantIdBytes, schemaName, tableName);
try {
- acquireLock(region, lockKey, locks);
- if (key != lockKey) {
- acquireLock(region, key, locks);
+ acquireLock(region, tableKey, locks);
+
+ // If the table key resides outside the region, return without doing anything
+ MetaDataMutationResult result = checkTableKeyInRegion(tableKey, region);
+ if (result != null) {
+ done.run(MetaDataMutationResult.toProto(result));
+ return;
}
- // Load parent table first
- PTable parentTable = null;
+
+ long clientTimeStamp = MetaDataUtil.getClientTimeStamp(tableMetadata);
ImmutableBytesPtr parentCacheKey = null;
- if (parentKey != null) {
- parentCacheKey = new ImmutableBytesPtr(parentKey);
- parentTable =
- loadTable(env, parentKey, parentCacheKey, clientTimeStamp,
+ if (parentTableName != null) {
+ // Check if the parent table resides in the same region. If not, don't worry about locking the parent table row
+ // or loading the parent table. For a view, the parent table that needs to be locked is the base physical table.
+ // For an index on view, the view header row needs to be locked.
+ result = checkTableKeyInRegion(parentTableKey, region);
+ if (result == null) {
+ acquireLock(region, parentTableKey, locks);
+ parentCacheKey = new ImmutableBytesPtr(parentTableKey);
+ PTable parentTable = loadTable(env, parentTableKey, parentCacheKey, clientTimeStamp,
clientTimeStamp);
- if (parentTable == null || isTableDeleted(parentTable)) {
- builder.setReturnCode(MetaDataProtos.MutationCode.PARENT_TABLE_NOT_FOUND);
- builder.setMutationTime(EnvironmentEdgeManager.currentTimeMillis());
- builder.setTable(PTableImpl.toProto(parentTable));
- done.run(builder.build());
- return;
- }
- // If parent table isn't at the expected sequence number, then return
- if (parentTable.getSequenceNumber() != MetaDataUtil
- .getParentSequenceNumber(tableMetadata)) {
- builder.setReturnCode(MetaDataProtos.MutationCode.CONCURRENT_TABLE_MUTATION);
- builder.setMutationTime(EnvironmentEdgeManager.currentTimeMillis());
- builder.setTable(PTableImpl.toProto(parentTable));
- done.run(builder.build());
- return;
+ if (parentTable == null || isTableDeleted(parentTable)) {
+ builder.setReturnCode(MetaDataProtos.MutationCode.PARENT_TABLE_NOT_FOUND);
+ builder.setMutationTime(EnvironmentEdgeManager.currentTimeMillis());
+ done.run(builder.build());
+ return;
+ }
+ long parentTableSeqNumber;
+ if (tableType == PTableType.VIEW && viewPhysicalTableRow != null && request.hasClientVersion()) {
+ // Starting 4.5, the client passes the sequence number of the physical table in the table metadata.
+ parentTableSeqNumber = MetaDataUtil.getSequenceNumber(viewPhysicalTableRow);
+ } else if (tableType == PTableType.VIEW && !request.hasClientVersion()) {
+ // Before 4.5, due to a bug, the parent table key wasn't available.
+ // So don't do anything and prevent the exception from being thrown.
+ parentTableSeqNumber = parentTable.getSequenceNumber();
+ } else {
+ parentTableSeqNumber = MetaDataUtil.getParentSequenceNumber(tableMetadata);
+ }
+ // If parent table isn't at the expected sequence number, then return
+ if (parentTable.getSequenceNumber() != parentTableSeqNumber) {
+ builder.setReturnCode(MetaDataProtos.MutationCode.CONCURRENT_TABLE_MUTATION);
+ builder.setMutationTime(EnvironmentEdgeManager.currentTimeMillis());
+ builder.setTable(PTableImpl.toProto(parentTable));
+ done.run(builder.build());
+ return;
+ }
}
}
// Load child table next
- ImmutableBytesPtr cacheKey = new ImmutableBytesPtr(key);
+ ImmutableBytesPtr cacheKey = new ImmutableBytesPtr(tableKey);
// Get as of latest timestamp so we can detect if we have a newer table that already
- // exists
- // without making an additional query
+ // exists without making an additional query
PTable table =
- loadTable(env, key, cacheKey, clientTimeStamp, HConstants.LATEST_TIMESTAMP);
+ loadTable(env, tableKey, cacheKey, clientTimeStamp, HConstants.LATEST_TIMESTAMP);
if (table != null) {
if (table.getTimeStamp() < clientTimeStamp) {
// If the table is older than the client time stamp and it's deleted,
@@ -1154,26 +1233,19 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
return;
}
}
- PTableType tableType = MetaDataUtil.getTableType(tableMetadata, GenericKeyValueBuilder.INSTANCE,
- new ImmutableBytesWritable());
// Add cell for ROW_KEY_ORDER_OPTIMIZABLE = true, as we know that new tables
// conform the correct row key. The exception is for a VIEW, which the client
// sends over depending on its base physical table.
if (tableType != PTableType.VIEW) {
- UpgradeUtil.addRowKeyOrderOptimizableCell(tableMetadata, key, clientTimeStamp);
+ UpgradeUtil.addRowKeyOrderOptimizableCell(tableMetadata, tableKey, clientTimeStamp);
}
- // TODO: Switch this to Region#batchMutate when we want to support indexes on the
- // system
- // table. Basically, we get all the locks that we don't already hold for all the
+ // TODO: Switch this to HRegion#batchMutate when we want to support indexes on the
+ // system table. Basically, we get all the locks that we don't already hold for all the
// tableMetadata rows. This ensures we don't have deadlock situations (ensuring
- // primary and
- // then index table locks are held, in that order). For now, we just don't support
- // indexing
- // on the system table. This is an issue because of the way we manage batch mutation
- // in the
- // Indexer.
- region.mutateRowsWithLocks(tableMetadata, Collections.<byte[]> emptySet(), HConstants.NO_NONCE,
- HConstants.NO_NONCE);
+ // primary and then index table locks are held, in that order). For now, we just don't support
+ // indexing on the system table. This is an issue because of the way we manage batch mutation
+ // in the Indexer.
+ region.mutateRowsWithLocks(tableMetadata, Collections.<byte[]> emptySet(), HConstants.NO_NONCE, HConstants.NO_NONCE);
// Invalidate the cache - the next getTable call will add it
// TODO: consider loading the table that was just created here, patching up the parent table, and updating the cache
@@ -1192,14 +1264,12 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
region.releaseRowLocks(locks);
}
} catch (Throwable t) {
- logger.error("createTable failed", t);
+ logger.error("createTable failed", t);
ProtobufUtil.setControllerException(controller,
- ServerUtil.createIOException(SchemaUtil.getTableName(schemaName, tableName), t));
+ ServerUtil.createIOException(SchemaUtil.getTableName(schemaName, tableName), t));
}
}
-
-
private static RowLock acquireLock(Region region, byte[] key, List<RowLock> locks)
throws IOException {
RowLock rowLock = region.getRowLock(key, true);
@@ -1609,10 +1679,6 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
}
- private boolean isvalidAttribute(Object obj1, Object obj2) {
- return (obj1!=null && obj1.equals(obj2)) || (obj1==null && obj2==null);
- }
-
private MetaDataMutationResult addRowsToChildViews(PTable table, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, TableViewFinderResult childViewsResult,
Region region, List<RowLock> locks) throws IOException, SQLException {
@@ -1924,7 +1990,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
@Override
- public void addColumn(RpcController controller, AddColumnRequest request,
+ public void addColumn(RpcController controller, final AddColumnRequest request,
RpcCallback<MetaDataResponse> done) {
try {
List<Mutation> tableMetaData = ProtobufUtil.getMutations(request);
@@ -1953,25 +2019,30 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
if (type == PTableType.TABLE || type == PTableType.SYSTEM) {
TableViewFinderResult childViewsResult = findChildViews(region, tenantId, table, PHYSICAL_TABLE_BYTES);
if (childViewsResult.hasViews()) {
- /*
- * Adding a column is not allowed if the meta-data for child view/s spans over
- * more than one region (since the changes cannot be made in a transactional fashion)
- * A base column count of 0 means that the metadata hasn't been upgraded yet or
- * the upgrade is currently in progress. If that is the case, disallow adding columns
- * for tables with views.
- */
- if (!childViewsResult.allViewsInSingleRegion() || table.getBaseColumnCount() == 0) {
- return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION,
- EnvironmentEdgeManager.currentTimeMillis(), null);
- } else {
- mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getResults().size() * tableMetaData.size());
- MetaDataMutationResult mutationResult = addRowsToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
- childViewsResult, region, locks);
- // return if we were not able to add the column successfully
- if (mutationResult!=null)
- return mutationResult;
- }
- }
+ /*
+ * Adding a column is not allowed if
+ * 1) The meta-data for child view/s spans over
+ * more than one region (since the changes cannot be made in a transactional fashion)
+ *
+ * 2) The base column count is 0 which means that the metadata hasn't been upgraded yet or
+ * the upgrade is currently in progress.
+ *
+ * 3) If the request is from a client that is older than 4.5 version of phoenix.
+ * Starting from 4.5, metadata requests have the client version included in them.
+ * We don't want to allow clients before 4.5 to add a column to the base table if it has views.
+ */
+ if (!childViewsResult.allViewsInSingleRegion() || table.getBaseColumnCount() == 0 || !request.hasClientVersion()) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION,
+ EnvironmentEdgeManager.currentTimeMillis(), null);
+ } else {
+ mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getResults().size() * tableMetaData.size());
+ MetaDataMutationResult mutationResult = addRowsToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
+ childViewsResult, region, locks);
+ // return if we were not able to add the column successfully
+ if (mutationResult!=null)
+ return mutationResult;
+ }
+ }
}
for (Mutation m : tableMetaData) {
byte[] key = m.getRow();
[26/50] [abbrv] phoenix git commit: PHOENIX-2109 - Joda time version
conflict between phoenix and pherf
Posted by ma...@apache.org.
PHOENIX-2109 - Joda time version conflict between phoenix and pherf
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/a772a4a0
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/a772a4a0
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/a772a4a0
Branch: refs/heads/calcite
Commit: a772a4a0ca3c9ac98335ce2148eb2b34d3ce1369
Parents: 70c542d
Author: Cody Marcel <co...@gmail.com>
Authored: Mon Jul 13 14:23:53 2015 -0700
Committer: Cody Marcel <co...@gmail.com>
Committed: Mon Jul 13 14:23:53 2015 -0700
----------------------------------------------------------------------
phoenix-pherf/pom.xml | 2 +-
.../src/it/java/org/apache/phoenix/pherf/DataIngestIT.java | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/a772a4a0/phoenix-pherf/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-pherf/pom.xml b/phoenix-pherf/pom.xml
index 0facbde..4d27305 100644
--- a/phoenix-pherf/pom.xml
+++ b/phoenix-pherf/pom.xml
@@ -219,7 +219,7 @@
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
- <version>1.6.2</version>
+ <version>${jodatime.version}</version>
</dependency>
<dependency>
<groupId>com.googlecode.java-diff-utils</groupId>
http://git-wip-us.apache.org/repos/asf/phoenix/blob/a772a4a0/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
index 828ac38..8a340b3 100644
--- a/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
+++ b/phoenix-pherf/src/it/java/org/apache/phoenix/pherf/DataIngestIT.java
@@ -27,6 +27,7 @@ import org.apache.phoenix.pherf.configuration.Scenario;
import org.apache.phoenix.pherf.rules.DataValue;
import org.apache.phoenix.pherf.rules.RulesApplier;
import org.apache.phoenix.pherf.workload.QueryExecutor;
+import org.apache.phoenix.pherf.workload.Workload;
import org.apache.phoenix.pherf.workload.WorkloadExecutor;
import org.apache.phoenix.pherf.workload.WriteWorkload;
import org.junit.Before;
@@ -68,6 +69,7 @@ public class DataIngestIT extends ResultBaseTestIT {
WriteWorkload loader = new WriteWorkload(util, parser, scenario);
WorkloadExecutor executor = new WorkloadExecutor();
executor.add(loader);
+ executor.get();
RulesApplier rulesApplier = loader.getRulesApplier();
List<Map> modelList = rulesApplier.getModelList();
@@ -90,6 +92,12 @@ public class DataIngestIT extends ResultBaseTestIT {
data.getDistribution() == Integer.MIN_VALUE);
}
}
+
+ // Run some queries
+ Workload query = new QueryExecutor(parser, util, executor.getPool());
+ executor.add(query);
+ executor.get();
+
} catch (Exception e) {
fail("We had an exception: " + e.getMessage());
}
[41/50] [abbrv] phoenix git commit: PHOENIX-2118 Remove/modfiy usages
of Guava StopWatch and deprecated ComparisonChain methods
Posted by ma...@apache.org.
PHOENIX-2118 Remove/modfiy usages of Guava StopWatch and deprecated ComparisonChain methods
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/a8f0d769
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/a8f0d769
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/a8f0d769
Branch: refs/heads/calcite
Commit: a8f0d7696b6ee105d55c7d3dce50563e816cd857
Parents: cf2bc55
Author: Samarth <sa...@salesforce.com>
Authored: Wed Jul 15 12:21:09 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Wed Jul 15 12:21:09 2015 -0700
----------------------------------------------------------------------
.../phoenix/monitoring/MetricsStopWatch.java | 8 +-
.../query/ConnectionQueryServicesImpl.java | 4 +-
.../java/org/apache/phoenix/query/KeyRange.java | 13 +---
.../apache/phoenix/util/PhoenixStopWatch.java | 81 ++++++++++++++++++++
4 files changed, 91 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/a8f0d769/phoenix-core/src/main/java/org/apache/phoenix/monitoring/MetricsStopWatch.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/monitoring/MetricsStopWatch.java b/phoenix-core/src/main/java/org/apache/phoenix/monitoring/MetricsStopWatch.java
index bffb9ad..ee260a8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/monitoring/MetricsStopWatch.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/monitoring/MetricsStopWatch.java
@@ -17,23 +17,23 @@
*/
package org.apache.phoenix.monitoring;
-import com.google.common.base.Stopwatch;
+import org.apache.phoenix.util.PhoenixStopWatch;
/**
*
* Stop watch that is cognizant of the fact whether or not metrics is enabled.
* If metrics isn't enabled it doesn't do anything. Otherwise, it delegates
- * calls to a {@code Stopwatch}.
+ * calls to a {@code PhoenixStopWatch}.
*
*/
final class MetricsStopWatch {
private final boolean isMetricsEnabled;
- private final Stopwatch stopwatch;
+ private final PhoenixStopWatch stopwatch;
MetricsStopWatch(boolean isMetricsEnabled) {
this.isMetricsEnabled = isMetricsEnabled;
- this.stopwatch = new Stopwatch();
+ this.stopwatch = new PhoenixStopWatch();
}
void start() {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/a8f0d769/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 52b038b..a17e28a 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
@@ -158,6 +158,7 @@ import org.apache.phoenix.util.JDBCUtil;
import org.apache.phoenix.util.MetaDataUtil;
import org.apache.phoenix.util.PhoenixContextExecutor;
import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.PhoenixStopWatch;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.ReadOnlyProps;
import org.apache.phoenix.util.SchemaUtil;
@@ -167,7 +168,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Joiner;
-import com.google.common.base.Stopwatch;
import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
@@ -757,7 +757,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
QueryServicesOptions.DEFAULT_DELAY_FOR_SCHEMA_UPDATE_CHECK);
boolean success = false;
int numTries = 1;
- Stopwatch watch = new Stopwatch();
+ PhoenixStopWatch watch = new PhoenixStopWatch();
watch.start();
do {
try {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/a8f0d769/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java b/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
index bca55e8..0612046 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/KeyRange.java
@@ -80,23 +80,18 @@ public class KeyRange implements Writable {
}
};
public static final Comparator<KeyRange> COMPARATOR = new Comparator<KeyRange>() {
- @SuppressWarnings("deprecation")
@Override public int compare(KeyRange o1, KeyRange o2) {
return ComparisonChain.start()
-// .compareFalseFirst(o1.lowerUnbound(), o2.lowerUnbound())
- .compare(o2.lowerUnbound(), o1.lowerUnbound())
+ .compareFalseFirst(o2.lowerUnbound(), o1.lowerUnbound())
.compare(o1.getLowerRange(), o2.getLowerRange(), Bytes.BYTES_COMPARATOR)
// we want o1 lower inclusive to come before o2 lower inclusive, but
// false comes before true, so we have to negate
-// .compareTrueFirst(o1.isLowerInclusive(), o2.isLowerInclusive())
- .compare(o2.isLowerInclusive(), o1.isLowerInclusive())
+ .compareFalseFirst(o2.isLowerInclusive(), o1.isLowerInclusive())
// for the same lower bounding, we want a finite upper bound to
// be ordered before an infinite upper bound
-// .compareTrueFirst(o1.upperUnbound(), o2.upperUnbound())
- .compare(o1.upperUnbound(), o2.upperUnbound())
+ .compareFalseFirst(o1.upperUnbound(), o2.upperUnbound())
.compare(o1.getUpperRange(), o2.getUpperRange(), Bytes.BYTES_COMPARATOR)
-// .compareFalseFirst(o1.isUpperInclusive(), o2.isUpperInclusive())
- .compare(o2.isUpperInclusive(), o1.isUpperInclusive())
+ .compareFalseFirst(o2.isUpperInclusive(), o1.isUpperInclusive())
.result();
}
};
http://git-wip-us.apache.org/repos/asf/phoenix/blob/a8f0d769/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixStopWatch.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixStopWatch.java b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixStopWatch.java
new file mode 100644
index 0000000..9001b0a
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixStopWatch.java
@@ -0,0 +1,81 @@
+/*
+ * 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.util;
+
+/**
+ * Bare-bones implementation of a stop watch that only measures time in milliseconds. If you want to be fancy then
+ * please use the guava Stopwatch. However, be warned that the Guava's Stopwatch is a beta class and is subject to
+ * incompatible changes and removal. So save the future upgrade pain and use this class instead.
+ */
+public class PhoenixStopWatch {
+ private boolean isRunning;
+ private long startTime;
+ private long elapsedTimeMs;
+
+ /**
+ * Creates a new stop watch without starting it.
+ */
+ public PhoenixStopWatch() {}
+
+ /**
+ * Starts the stopwatch.
+ *
+ * @return this {@code PhoenixStopWatch} instance
+ * @throws IllegalStateException
+ * if the stopwatch is already running.
+ */
+ public PhoenixStopWatch start() {
+ long currentTime = System.currentTimeMillis();
+ if (isRunning) { throw new IllegalStateException("Watch is already running"); }
+ startTime = currentTime;
+ isRunning = true;
+ return this;
+ }
+
+ /**
+ * Stops the stopwatch. Future calls to {@link #elapsedMillis()} will return the fixed duration that had elapsed up
+ * to this point.
+ *
+ * @return this {@code PhoenixStopWatch} instance
+ * @throws IllegalStateException
+ * if the stopwatch is already stopped.
+ */
+ public PhoenixStopWatch stop() {
+ long currentTime = System.currentTimeMillis();
+ if (!isRunning) { throw new IllegalStateException("Watch wasn't started"); }
+ elapsedTimeMs = currentTime - startTime;
+ startTime = 0;
+ isRunning = false;
+ return this;
+ }
+
+ /**
+ * Returns the current elapsed time shown on this stopwatch, expressed in milliseconds.
+ */
+ public long elapsedMillis() {
+ return elapsedTimeMs;
+ }
+
+ /**
+ * Returns {@code true} if {@link #start()} has been called on this stopwatch, and {@link #stop()} has not been
+ * called since the last call to {@code start()}.
+ */
+ public boolean isRunning() {
+ return isRunning;
+ }
+}
[47/50] [abbrv] phoenix git commit: PHOENIX-2125 ORDER BY on full PK
on salted table does not work
Posted by ma...@apache.org.
PHOENIX-2125 ORDER BY on full PK on salted table does not work
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/b329e85b
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/b329e85b
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/b329e85b
Branch: refs/heads/calcite
Commit: b329e85b697575fcebcde9555c991038d14e4a3c
Parents: f006df5
Author: Samarth <sa...@salesforce.com>
Authored: Fri Jul 17 17:30:56 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Fri Jul 17 17:30:56 2015 -0700
----------------------------------------------------------------------
.../org/apache/phoenix/execute/ScanPlan.java | 12 ++++++-
.../java/org/apache/phoenix/util/ScanUtil.java | 6 +++-
.../phoenix/compile/QueryCompilerTest.java | 36 ++++++++++++++------
.../expression/ArrayToStringFunctionTest.java | 4 ++-
4 files changed, 44 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b329e85b/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
index fd9f8ad..e9b8a3a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
@@ -185,9 +185,19 @@ public class ScanPlan extends BaseQueryPlan {
if (isOrdered) {
scanner = new MergeSortTopNResultIterator(iterators, limit, orderBy.getOrderByExpressions());
} else {
- if ((isSalted || table.getIndexType() == IndexType.LOCAL) && ScanUtil.forceRowKeyOrder(context)) {
+ if ((isSalted || table.getIndexType() == IndexType.LOCAL) && ScanUtil.shouldRowsBeInRowKeyOrder(orderBy, context)) {
+ /*
+ * For salted tables or local index, a merge sort is needed if:
+ * 1) The config phoenix.query.force.rowkeyorder is set to true
+ * 2) Or if the query has an order by that wants to sort
+ * the results by the row key (forward or reverse ordering)
+ */
scanner = new MergeSortRowKeyResultIterator(iterators, isSalted ? SaltingUtil.NUM_SALTING_BYTES : 0, orderBy == OrderBy.REV_ROW_KEY_ORDER_BY);
} else if (useRoundRobinIterator()) {
+ /*
+ * For any kind of tables, round robin is possible if there is
+ * no ordering of rows needed.
+ */
scanner = new RoundRobinResultIterator(iterators, this);
} else {
scanner = new ConcatResultIterator(iterators);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b329e85b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
index d63edbb..9d104ca 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
@@ -677,11 +677,15 @@ public class ScanUtil {
* not even row key order. Also no point doing round robin of scanners if fetch size
* is 1.
*/
- return fetchSize > 1 && !forceRowKeyOrder(context) && (orderBy.getOrderByExpressions().isEmpty() && orderBy != FWD_ROW_KEY_ORDER_BY && orderBy != REV_ROW_KEY_ORDER_BY);
+ return fetchSize > 1 && !shouldRowsBeInRowKeyOrder(orderBy, context) && orderBy.getOrderByExpressions().isEmpty();
}
public static boolean forceRowKeyOrder(StatementContext context) {
return context.getConnection().getQueryServices().getProps()
.getBoolean(QueryServices.FORCE_ROW_KEY_ORDER_ATTRIB, QueryServicesOptions.DEFAULT_FORCE_ROW_KEY_ORDER);
}
+
+ public static boolean shouldRowsBeInRowKeyOrder(OrderBy orderBy, StatementContext context) {
+ return forceRowKeyOrder(context) || orderBy == FWD_ROW_KEY_ORDER_BY || orderBy == REV_ROW_KEY_ORDER_BY;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b329e85b/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 0f34582..98b130e 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
@@ -1855,11 +1855,17 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
Properties props = new Properties();
props.setProperty(QueryServices.FORCE_ROW_KEY_ORDER_ATTRIB, Boolean.toString(true));
Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.createStatement().execute("CREATE TABLE t (k1 char(2) not null, k2 varchar not null, k3 integer not null, v varchar, constraint pk primary key(k1,k2,k3))");
+ testForceRowKeyOrder(conn, false);
+ testForceRowKeyOrder(conn, true);
+ }
+
+ private void testForceRowKeyOrder(Connection conn, boolean isSalted) throws SQLException {
+ String tableName = "tablename" + (isSalted ? "_salt" : "");
+ conn.createStatement().execute("CREATE TABLE " + tableName + " (k1 char(2) not null, k2 varchar not null, k3 integer not null, v varchar, constraint pk primary key(k1,k2,k3))");
String[] queries = {
- "SELECT 1 FROM T ",
- "SELECT 1 FROM T WHERE V = 'c'",
- "SELECT 1 FROM T WHERE (k1, k2, k3) > ('a', 'ab', 1)",
+ "SELECT 1 FROM " + tableName ,
+ "SELECT 1 FROM " + tableName + " WHERE V = 'c'",
+ "SELECT 1 FROM " + tableName + " WHERE (k1, k2, k3) > ('a', 'ab', 1)",
};
String query;
for (int i = 0; i < queries.length; i++) {
@@ -1874,13 +1880,21 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
Properties props = new Properties();
props.setProperty(QueryServices.FORCE_ROW_KEY_ORDER_ATTRIB, Boolean.toString(false));
Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.createStatement().execute("CREATE TABLE t (k1 char(2) not null, k2 varchar not null, k3 integer not null, v varchar, constraint pk primary key(k1,k2,k3))");
+ testOrderByOrGroupByDoesntUseRoundRobin(conn, true);
+ testOrderByOrGroupByDoesntUseRoundRobin(conn, false);
+ }
+
+ private void testOrderByOrGroupByDoesntUseRoundRobin(Connection conn, boolean salted) throws SQLException {
+ String tableName = "orderbygroupbytable" + (salted ? "_salt" : "");
+ conn.createStatement().execute("CREATE TABLE " + tableName + " (k1 char(2) not null, k2 varchar not null, k3 integer not null, v varchar, constraint pk primary key(k1,k2,k3))");
String[] queries = {
- "SELECT 1 FROM T ORDER BY K1",
- "SELECT 1 FROM T WHERE V = 'c' ORDER BY K1, K2",
- "SELECT 1 FROM T WHERE (k1,k2, k3) > ('a', 'ab', 1) ORDER BY V",
- "SELECT 1 FROM T GROUP BY V",
- "SELECT 1 FROM T GROUP BY K1, V, K2 ORDER BY V",
+ "SELECT 1 FROM " + tableName + " ORDER BY K1",
+ "SELECT 1 FROM " + tableName + " WHERE V = 'c' ORDER BY K1, K2",
+ "SELECT 1 FROM " + tableName + " WHERE V = 'c' ORDER BY K1, K2, K3",
+ "SELECT 1 FROM " + tableName + " WHERE V = 'c' ORDER BY K3",
+ "SELECT 1 FROM " + tableName + " WHERE (k1,k2, k3) > ('a', 'ab', 1) ORDER BY V",
+ "SELECT 1 FROM " + tableName + " GROUP BY V",
+ "SELECT 1 FROM " + tableName + " GROUP BY K1, V, K2 ORDER BY V",
};
String query;
for (int i = 0; i < queries.length; i++) {
@@ -1889,7 +1903,7 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
assertFalse("Expected plan to not use round robin iterator " + query, plan.useRoundRobinIterator());
}
}
-
+
@Test
public void testSelectColumnsInOneFamily() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
http://git-wip-us.apache.org/repos/asf/phoenix/blob/b329e85b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
index 92eb6b5..d97f117 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
@@ -30,6 +30,7 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.expression.function.ArrayToStringFunction;
import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.types.*;
+import org.junit.Ignore;
import org.junit.Test;
import com.google.common.collect.Lists;
@@ -132,8 +133,9 @@ public class ArrayToStringFunctionTest {
String expected = "1.1, 2.2, 3.3, 4.4, 5.5";
test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
}
-
+
@Test
+ @Ignore
public void testDate() throws SQLException {
PDataType type = PDateArray.INSTANCE;
PDataType base = PDate.INSTANCE;
[20/50] [abbrv] phoenix git commit: PHOENIX-2063 Addendum patch to
fix connection usage
Posted by ma...@apache.org.
PHOENIX-2063 Addendum patch to fix connection usage
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/997de5e6
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/997de5e6
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/997de5e6
Branch: refs/heads/calcite
Commit: 997de5e6cab988018e723ed29a53da1bae61def4
Parents: 3b1bfa0
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Jul 9 22:55:25 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Jul 9 22:55:25 2015 -0700
----------------------------------------------------------------------
.../phoenix/end2end/RowValueConstructorIT.java | 28 +++++++++++++++-----
1 file changed, 21 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/997de5e6/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
index 0cf5455..b9e50a4 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
@@ -1426,10 +1426,11 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
@Test
public void testCountDistinct1() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
+ Connection conn = nextConnection(getUrl());
String ddl = "CREATE TABLE regions1 (region_name VARCHAR PRIMARY KEY, a INTEGER, b INTEGER)";
conn.createStatement().execute(ddl);
- conn.commit();
+
+ conn = nextConnection(getUrl());
PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('a', 6,3)");
stmt.execute();
stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('b', 2,4)");
@@ -1437,18 +1438,23 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('c', 6,3)");
stmt.execute();
conn.commit();
+
+ conn = nextConnection(getUrl());
ResultSet rs;
rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions1");
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
+ conn.close();
}
@Test
public void testCountDistinct2() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
+ Connection conn = nextConnection(getUrl());
String ddl = "CREATE TABLE regions2 (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
conn.createStatement().execute(ddl);
conn.commit();
+
+ conn = nextConnection(getUrl());
PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('a', 'fooo','abc')");
stmt.execute();
stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('b', 'off','bac')");
@@ -1456,6 +1462,8 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('c', 'fooo', 'abc')");
stmt.execute();
conn.commit();
+
+ conn = nextConnection(getUrl());
ResultSet rs;
rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions2");
assertTrue(rs.next());
@@ -1464,10 +1472,11 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
@Test
public void testCountDistinct3() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
+ Connection conn = nextConnection(getUrl());
String ddl = "CREATE TABLE regions3 (region_name VARCHAR PRIMARY KEY, a Boolean, b Boolean)";
conn.createStatement().execute(ddl);
- conn.commit();
+
+ conn = nextConnection(getUrl());
PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('a', true, true)");
stmt.execute();
stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('b', true, False)");
@@ -1477,6 +1486,8 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('d', true, false)");
stmt.execute();
conn.commit();
+
+ conn = nextConnection(getUrl());
ResultSet rs;
rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions3");
assertTrue(rs.next());
@@ -1485,10 +1496,11 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
@Test
public void testCountDistinct4() throws Exception {
- Connection conn = DriverManager.getConnection(getUrl());
+ Connection conn = nextConnection(getUrl());
String ddl = "CREATE TABLE regions4 (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
conn.createStatement().execute(ddl);
- conn.commit();
+
+ conn = nextConnection(getUrl());
PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('a', 'fooo','abc')");
stmt.execute();
stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('b', 'off','bac')");
@@ -1496,6 +1508,8 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('c', 'foo', 'abc')");
stmt.execute();
conn.commit();
+
+ conn = nextConnection(getUrl());
ResultSet rs;
rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions4");
assertTrue(rs.next());
[22/50] [abbrv] phoenix git commit: PHOENIX-2107 Update JDBC version
to 4.5.0
Posted by ma...@apache.org.
PHOENIX-2107 Update JDBC version to 4.5.0
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/81b3cb35
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/81b3cb35
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/81b3cb35
Branch: refs/heads/calcite
Commit: 81b3cb35679adf7772266f2aed9456273a8b0012
Parents: 39afa9f
Author: Samarth <sa...@salesforce.com>
Authored: Fri Jul 10 11:15:16 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Fri Jul 10 11:15:16 2015 -0700
----------------------------------------------------------------------
.../main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/81b3cb35/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java
index 9009e7c..013f7a6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java
@@ -55,7 +55,7 @@ import com.google.protobuf.ByteString;
*/
public abstract class MetaDataProtocol extends MetaDataService {
public static final int PHOENIX_MAJOR_VERSION = 4;
- public static final int PHOENIX_MINOR_VERSION = 4;
+ public static final int PHOENIX_MINOR_VERSION = 5;
public static final int PHOENIX_PATCH_NUMBER = 0;
public static final int PHOENIX_VERSION =
VersionUtil.encodeVersion(PHOENIX_MAJOR_VERSION, PHOENIX_MINOR_VERSION, PHOENIX_PATCH_NUMBER);
[15/50] [abbrv] phoenix git commit: PHOENIX-2063 Row value
constructor doesn't work when used in COUNT DISTINCT (Dumindu Buddhika)
Posted by ma...@apache.org.
PHOENIX-2063 Row value constructor doesn't work when used in COUNT
DISTINCT (Dumindu Buddhika)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/fa2d79a0
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/fa2d79a0
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/fa2d79a0
Branch: refs/heads/calcite
Commit: fa2d79a0162497761dd4568e3f8f343063b6afaa
Parents: aa4c900
Author: ramkrishna <ra...@gmail.com>
Authored: Thu Jul 9 10:18:10 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Thu Jul 9 10:18:10 2015 +0530
----------------------------------------------------------------------
.../phoenix/end2end/RowValueConstructorIT.java | 78 ++++++++++++++++++++
.../aggregator/ServerAggregators.java | 1 +
2 files changed, 79 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fa2d79a0/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
index e227eb0..0cf5455 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
@@ -1423,4 +1423,82 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
assertFalse(rs.next());
conn.close();
}
+
+ @Test
+ public void testCountDistinct1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ String ddl = "CREATE TABLE regions1 (region_name VARCHAR PRIMARY KEY, a INTEGER, b INTEGER)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('a', 6,3)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('b', 2,4)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('c', 6,3)");
+ stmt.execute();
+ conn.commit();
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions1");
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ }
+
+ @Test
+ public void testCountDistinct2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ String ddl = "CREATE TABLE regions2 (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('a', 'fooo','abc')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('b', 'off','bac')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('c', 'fooo', 'abc')");
+ stmt.execute();
+ conn.commit();
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions2");
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ }
+
+ @Test
+ public void testCountDistinct3() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ String ddl = "CREATE TABLE regions3 (region_name VARCHAR PRIMARY KEY, a Boolean, b Boolean)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('a', true, true)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('b', true, False)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('c', true, true)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('d', true, false)");
+ stmt.execute();
+ conn.commit();
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions3");
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ }
+
+ @Test
+ public void testCountDistinct4() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ String ddl = "CREATE TABLE regions4 (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('a', 'fooo','abc')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('b', 'off','bac')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('c', 'foo', 'abc')");
+ stmt.execute();
+ conn.commit();
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions4");
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fa2d79a0/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/ServerAggregators.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/ServerAggregators.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/ServerAggregators.java
index 8792c91..01ca733 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/ServerAggregators.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/ServerAggregators.java
@@ -59,6 +59,7 @@ public class ServerAggregators extends Aggregators {
if (expressions[i].evaluate(result, ptr) && ptr.getLength() != 0) {
aggregators[i].aggregate(result, ptr);
}
+ expressions[i].reset();
}
}
[38/50] [abbrv] phoenix git commit: PHOENIX-2111 Race condition on
creation of new view and adding of column to base table
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9f09f1a5/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/MetaDataProtos.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/MetaDataProtos.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/MetaDataProtos.java
index acb32d2..a121d28 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/MetaDataProtos.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/MetaDataProtos.java
@@ -1811,6 +1811,16 @@ public final class MetaDataProtos {
* <code>required int64 clientTimestamp = 5;</code>
*/
long getClientTimestamp();
+
+ // optional int32 clientVersion = 6;
+ /**
+ * <code>optional int32 clientVersion = 6;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 6;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code GetTableRequest}
@@ -1888,6 +1898,11 @@ public final class MetaDataProtos {
clientTimestamp_ = input.readInt64();
break;
}
+ case 48: {
+ bitField0_ |= 0x00000020;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -2008,12 +2023,29 @@ public final class MetaDataProtos {
return clientTimestamp_;
}
+ // optional int32 clientVersion = 6;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 6;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 6;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ /**
+ * <code>optional int32 clientVersion = 6;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tenantId_ = com.google.protobuf.ByteString.EMPTY;
schemaName_ = com.google.protobuf.ByteString.EMPTY;
tableName_ = com.google.protobuf.ByteString.EMPTY;
tableTimestamp_ = 0L;
clientTimestamp_ = 0L;
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -2062,6 +2094,9 @@ public final class MetaDataProtos {
if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeInt64(5, clientTimestamp_);
}
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ output.writeInt32(6, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -2091,6 +2126,10 @@ public final class MetaDataProtos {
size += com.google.protobuf.CodedOutputStream
.computeInt64Size(5, clientTimestamp_);
}
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(6, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -2139,6 +2178,11 @@ public final class MetaDataProtos {
result = result && (getClientTimestamp()
== other.getClientTimestamp());
}
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -2172,6 +2216,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + CLIENTTIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + hashLong(getClientTimestamp());
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -2291,6 +2339,8 @@ public final class MetaDataProtos {
bitField0_ = (bitField0_ & ~0x00000008);
clientTimestamp_ = 0L;
bitField0_ = (bitField0_ & ~0x00000010);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000020);
return this;
}
@@ -2339,6 +2389,10 @@ public final class MetaDataProtos {
to_bitField0_ |= 0x00000010;
}
result.clientTimestamp_ = clientTimestamp_;
+ if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+ to_bitField0_ |= 0x00000020;
+ }
+ result.clientVersion_ = clientVersion_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -2370,6 +2424,9 @@ public final class MetaDataProtos {
if (other.hasClientTimestamp()) {
setClientTimestamp(other.getClientTimestamp());
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -2591,6 +2648,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 6;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 6;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ /**
+ * <code>optional int32 clientVersion = 6;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 6;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000020;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 6;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000020);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:GetTableRequest)
}
@@ -2652,6 +2742,16 @@ public final class MetaDataProtos {
* <code>required int64 clientTimestamp = 4;</code>
*/
long getClientTimestamp();
+
+ // optional int32 clientVersion = 5;
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code GetFunctionsRequest}
@@ -2743,6 +2843,11 @@ public final class MetaDataProtos {
clientTimestamp_ = input.readInt64();
break;
}
+ case 40: {
+ bitField0_ |= 0x00000004;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -2867,11 +2972,28 @@ public final class MetaDataProtos {
return clientTimestamp_;
}
+ // optional int32 clientVersion = 5;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 5;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tenantId_ = com.google.protobuf.ByteString.EMPTY;
functionNames_ = java.util.Collections.emptyList();
functionTimestamps_ = java.util.Collections.emptyList();
clientTimestamp_ = 0L;
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -2905,6 +3027,9 @@ public final class MetaDataProtos {
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeInt64(4, clientTimestamp_);
}
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeInt32(5, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -2940,6 +3065,10 @@ public final class MetaDataProtos {
size += com.google.protobuf.CodedOutputStream
.computeInt64Size(4, clientTimestamp_);
}
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(5, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -2977,6 +3106,11 @@ public final class MetaDataProtos {
result = result && (getClientTimestamp()
== other.getClientTimestamp());
}
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -3006,6 +3140,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + CLIENTTIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + hashLong(getClientTimestamp());
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -3123,6 +3261,8 @@ public final class MetaDataProtos {
bitField0_ = (bitField0_ & ~0x00000004);
clientTimestamp_ = 0L;
bitField0_ = (bitField0_ & ~0x00000008);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@@ -3169,6 +3309,10 @@ public final class MetaDataProtos {
to_bitField0_ |= 0x00000002;
}
result.clientTimestamp_ = clientTimestamp_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.clientVersion_ = clientVersion_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -3211,6 +3355,9 @@ public final class MetaDataProtos {
if (other.hasClientTimestamp()) {
setClientTimestamp(other.getClientTimestamp());
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -3453,6 +3600,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 5;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000010;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:GetFunctionsRequest)
}
@@ -3480,6 +3660,16 @@ public final class MetaDataProtos {
* <code>repeated bytes tableMetadataMutations = 1;</code>
*/
com.google.protobuf.ByteString getTableMetadataMutations(int index);
+
+ // optional int32 clientVersion = 2;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code CreateTableRequest}
@@ -3544,6 +3734,11 @@ public final class MetaDataProtos {
tableMetadataMutations_.add(input.readBytes());
break;
}
+ case 16: {
+ bitField0_ |= 0x00000001;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -3586,6 +3781,7 @@ public final class MetaDataProtos {
return PARSER;
}
+ private int bitField0_;
// repeated bytes tableMetadataMutations = 1;
public static final int TABLEMETADATAMUTATIONS_FIELD_NUMBER = 1;
private java.util.List<com.google.protobuf.ByteString> tableMetadataMutations_;
@@ -3609,8 +3805,25 @@ public final class MetaDataProtos {
return tableMetadataMutations_.get(index);
}
+ // optional int32 clientVersion = 2;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 2;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tableMetadataMutations_ = java.util.Collections.emptyList();
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -3627,6 +3840,9 @@ public final class MetaDataProtos {
for (int i = 0; i < tableMetadataMutations_.size(); i++) {
output.writeBytes(1, tableMetadataMutations_.get(i));
}
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeInt32(2, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -3645,6 +3861,10 @@ public final class MetaDataProtos {
size += dataSize;
size += 1 * getTableMetadataMutationsList().size();
}
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(2, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -3670,6 +3890,11 @@ public final class MetaDataProtos {
boolean result = true;
result = result && getTableMetadataMutationsList()
.equals(other.getTableMetadataMutationsList());
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -3687,6 +3912,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + TABLEMETADATAMUTATIONS_FIELD_NUMBER;
hash = (53 * hash) + getTableMetadataMutationsList().hashCode();
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -3802,6 +4031,8 @@ public final class MetaDataProtos {
super.clear();
tableMetadataMutations_ = java.util.Collections.emptyList();
bitField0_ = (bitField0_ & ~0x00000001);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
return this;
}
@@ -3829,11 +4060,17 @@ public final class MetaDataProtos {
public org.apache.phoenix.coprocessor.generated.MetaDataProtos.CreateTableRequest buildPartial() {
org.apache.phoenix.coprocessor.generated.MetaDataProtos.CreateTableRequest result = new org.apache.phoenix.coprocessor.generated.MetaDataProtos.CreateTableRequest(this);
int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
tableMetadataMutations_ = java.util.Collections.unmodifiableList(tableMetadataMutations_);
bitField0_ = (bitField0_ & ~0x00000001);
}
result.tableMetadataMutations_ = tableMetadataMutations_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.clientVersion_ = clientVersion_;
+ result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
@@ -3859,6 +4096,9 @@ public final class MetaDataProtos {
}
onChanged();
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -3958,6 +4198,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 2;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000002;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:CreateTableRequest)
}
@@ -4005,6 +4278,16 @@ public final class MetaDataProtos {
* <code>optional bool replace = 3;</code>
*/
boolean getReplace();
+
+ // optional int32 clientVersion = 4;
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code CreateFunctionRequest}
@@ -4079,6 +4362,11 @@ public final class MetaDataProtos {
replace_ = input.readBool();
break;
}
+ case 32: {
+ bitField0_ |= 0x00000004;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -4177,10 +4465,27 @@ public final class MetaDataProtos {
return replace_;
}
+ // optional int32 clientVersion = 4;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 4;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tableMetadataMutations_ = java.util.Collections.emptyList();
temporary_ = false;
replace_ = false;
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -4207,6 +4512,9 @@ public final class MetaDataProtos {
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBool(3, replace_);
}
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeInt32(4, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -4233,6 +4541,10 @@ public final class MetaDataProtos {
size += com.google.protobuf.CodedOutputStream
.computeBoolSize(3, replace_);
}
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(4, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -4268,6 +4580,11 @@ public final class MetaDataProtos {
result = result && (getReplace()
== other.getReplace());
}
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -4293,6 +4610,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + REPLACE_FIELD_NUMBER;
hash = (53 * hash) + hashBoolean(getReplace());
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -4412,6 +4733,8 @@ public final class MetaDataProtos {
bitField0_ = (bitField0_ & ~0x00000002);
replace_ = false;
bitField0_ = (bitField0_ & ~0x00000004);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000008);
return this;
}
@@ -4453,6 +4776,10 @@ public final class MetaDataProtos {
to_bitField0_ |= 0x00000002;
}
result.replace_ = replace_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.clientVersion_ = clientVersion_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -4485,6 +4812,9 @@ public final class MetaDataProtos {
if (other.hasReplace()) {
setReplace(other.getReplace());
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -4654,6 +4984,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 4;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000008;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:CreateFunctionRequest)
}
@@ -4706,6 +5069,16 @@ public final class MetaDataProtos {
* <code>optional bool cascade = 3;</code>
*/
boolean getCascade();
+
+ // optional int32 clientVersion = 4;
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code DropTableRequest}
@@ -4776,6 +5149,11 @@ public final class MetaDataProtos {
cascade_ = input.readBool();
break;
}
+ case 32: {
+ bitField0_ |= 0x00000004;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -4901,10 +5279,27 @@ public final class MetaDataProtos {
return cascade_;
}
+ // optional int32 clientVersion = 4;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 4;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tableMetadataMutations_ = java.util.Collections.emptyList();
tableType_ = "";
cascade_ = false;
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -4931,6 +5326,9 @@ public final class MetaDataProtos {
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBool(3, cascade_);
}
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeInt32(4, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -4957,6 +5355,10 @@ public final class MetaDataProtos {
size += com.google.protobuf.CodedOutputStream
.computeBoolSize(3, cascade_);
}
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(4, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -4992,6 +5394,11 @@ public final class MetaDataProtos {
result = result && (getCascade()
== other.getCascade());
}
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -5017,6 +5424,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + CASCADE_FIELD_NUMBER;
hash = (53 * hash) + hashBoolean(getCascade());
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -5132,6 +5543,8 @@ public final class MetaDataProtos {
bitField0_ = (bitField0_ & ~0x00000002);
cascade_ = false;
bitField0_ = (bitField0_ & ~0x00000004);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000008);
return this;
}
@@ -5173,6 +5586,10 @@ public final class MetaDataProtos {
to_bitField0_ |= 0x00000002;
}
result.cascade_ = cascade_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.clientVersion_ = clientVersion_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -5207,6 +5624,9 @@ public final class MetaDataProtos {
if (other.hasCascade()) {
setCascade(other.getCascade());
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -5417,6 +5837,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 4;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000008;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 4;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:DropTableRequest)
}
@@ -5444,6 +5897,16 @@ public final class MetaDataProtos {
* <code>repeated bytes tableMetadataMutations = 1;</code>
*/
com.google.protobuf.ByteString getTableMetadataMutations(int index);
+
+ // optional int32 clientVersion = 2;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code AddColumnRequest}
@@ -5504,6 +5967,11 @@ public final class MetaDataProtos {
tableMetadataMutations_.add(input.readBytes());
break;
}
+ case 16: {
+ bitField0_ |= 0x00000001;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -5546,6 +6014,7 @@ public final class MetaDataProtos {
return PARSER;
}
+ private int bitField0_;
// repeated bytes tableMetadataMutations = 1;
public static final int TABLEMETADATAMUTATIONS_FIELD_NUMBER = 1;
private java.util.List<com.google.protobuf.ByteString> tableMetadataMutations_;
@@ -5569,8 +6038,25 @@ public final class MetaDataProtos {
return tableMetadataMutations_.get(index);
}
+ // optional int32 clientVersion = 2;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 2;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tableMetadataMutations_ = java.util.Collections.emptyList();
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -5587,6 +6073,9 @@ public final class MetaDataProtos {
for (int i = 0; i < tableMetadataMutations_.size(); i++) {
output.writeBytes(1, tableMetadataMutations_.get(i));
}
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeInt32(2, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -5605,6 +6094,10 @@ public final class MetaDataProtos {
size += dataSize;
size += 1 * getTableMetadataMutationsList().size();
}
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(2, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -5630,6 +6123,11 @@ public final class MetaDataProtos {
boolean result = true;
result = result && getTableMetadataMutationsList()
.equals(other.getTableMetadataMutationsList());
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -5647,6 +6145,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + TABLEMETADATAMUTATIONS_FIELD_NUMBER;
hash = (53 * hash) + getTableMetadataMutationsList().hashCode();
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -5758,6 +6260,8 @@ public final class MetaDataProtos {
super.clear();
tableMetadataMutations_ = java.util.Collections.emptyList();
bitField0_ = (bitField0_ & ~0x00000001);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
return this;
}
@@ -5785,11 +6289,17 @@ public final class MetaDataProtos {
public org.apache.phoenix.coprocessor.generated.MetaDataProtos.AddColumnRequest buildPartial() {
org.apache.phoenix.coprocessor.generated.MetaDataProtos.AddColumnRequest result = new org.apache.phoenix.coprocessor.generated.MetaDataProtos.AddColumnRequest(this);
int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
tableMetadataMutations_ = java.util.Collections.unmodifiableList(tableMetadataMutations_);
bitField0_ = (bitField0_ & ~0x00000001);
}
result.tableMetadataMutations_ = tableMetadataMutations_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.clientVersion_ = clientVersion_;
+ result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
@@ -5815,6 +6325,9 @@ public final class MetaDataProtos {
}
onChanged();
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -5914,6 +6427,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 2;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000002;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:AddColumnRequest)
}
@@ -5941,6 +6487,16 @@ public final class MetaDataProtos {
* <code>repeated bytes tableMetadataMutations = 1;</code>
*/
com.google.protobuf.ByteString getTableMetadataMutations(int index);
+
+ // optional int32 clientVersion = 2;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code DropColumnRequest}
@@ -6001,6 +6557,11 @@ public final class MetaDataProtos {
tableMetadataMutations_.add(input.readBytes());
break;
}
+ case 16: {
+ bitField0_ |= 0x00000001;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -6043,6 +6604,7 @@ public final class MetaDataProtos {
return PARSER;
}
+ private int bitField0_;
// repeated bytes tableMetadataMutations = 1;
public static final int TABLEMETADATAMUTATIONS_FIELD_NUMBER = 1;
private java.util.List<com.google.protobuf.ByteString> tableMetadataMutations_;
@@ -6066,8 +6628,25 @@ public final class MetaDataProtos {
return tableMetadataMutations_.get(index);
}
+ // optional int32 clientVersion = 2;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 2;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tableMetadataMutations_ = java.util.Collections.emptyList();
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -6084,6 +6663,9 @@ public final class MetaDataProtos {
for (int i = 0; i < tableMetadataMutations_.size(); i++) {
output.writeBytes(1, tableMetadataMutations_.get(i));
}
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeInt32(2, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -6102,6 +6684,10 @@ public final class MetaDataProtos {
size += dataSize;
size += 1 * getTableMetadataMutationsList().size();
}
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(2, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -6127,6 +6713,11 @@ public final class MetaDataProtos {
boolean result = true;
result = result && getTableMetadataMutationsList()
.equals(other.getTableMetadataMutationsList());
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -6144,6 +6735,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + TABLEMETADATAMUTATIONS_FIELD_NUMBER;
hash = (53 * hash) + getTableMetadataMutationsList().hashCode();
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -6255,6 +6850,8 @@ public final class MetaDataProtos {
super.clear();
tableMetadataMutations_ = java.util.Collections.emptyList();
bitField0_ = (bitField0_ & ~0x00000001);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
return this;
}
@@ -6282,11 +6879,17 @@ public final class MetaDataProtos {
public org.apache.phoenix.coprocessor.generated.MetaDataProtos.DropColumnRequest buildPartial() {
org.apache.phoenix.coprocessor.generated.MetaDataProtos.DropColumnRequest result = new org.apache.phoenix.coprocessor.generated.MetaDataProtos.DropColumnRequest(this);
int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
tableMetadataMutations_ = java.util.Collections.unmodifiableList(tableMetadataMutations_);
bitField0_ = (bitField0_ & ~0x00000001);
}
result.tableMetadataMutations_ = tableMetadataMutations_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.clientVersion_ = clientVersion_;
+ result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
@@ -6312,6 +6915,9 @@ public final class MetaDataProtos {
}
onChanged();
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -6411,6 +7017,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 2;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000002;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:DropColumnRequest)
}
@@ -6448,6 +7087,16 @@ public final class MetaDataProtos {
* <code>optional bool ifExists = 2;</code>
*/
boolean getIfExists();
+
+ // optional int32 clientVersion = 3;
+ /**
+ * <code>optional int32 clientVersion = 3;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 3;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code DropFunctionRequest}
@@ -6513,6 +7162,11 @@ public final class MetaDataProtos {
ifExists_ = input.readBool();
break;
}
+ case 24: {
+ bitField0_ |= 0x00000002;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -6595,9 +7249,26 @@ public final class MetaDataProtos {
return ifExists_;
}
+ // optional int32 clientVersion = 3;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 3;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 3;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional int32 clientVersion = 3;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tableMetadataMutations_ = java.util.Collections.emptyList();
ifExists_ = false;
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -6617,6 +7288,9 @@ public final class MetaDataProtos {
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeBool(2, ifExists_);
}
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeInt32(3, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -6639,6 +7313,10 @@ public final class MetaDataProtos {
size += com.google.protobuf.CodedOutputStream
.computeBoolSize(2, ifExists_);
}
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(3, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -6669,6 +7347,11 @@ public final class MetaDataProtos {
result = result && (getIfExists()
== other.getIfExists());
}
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -6690,6 +7373,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + IFEXISTS_FIELD_NUMBER;
hash = (53 * hash) + hashBoolean(getIfExists());
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -6803,6 +7490,8 @@ public final class MetaDataProtos {
bitField0_ = (bitField0_ & ~0x00000001);
ifExists_ = false;
bitField0_ = (bitField0_ & ~0x00000002);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000004);
return this;
}
@@ -6840,6 +7529,10 @@ public final class MetaDataProtos {
to_bitField0_ |= 0x00000001;
}
result.ifExists_ = ifExists_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.clientVersion_ = clientVersion_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -6869,6 +7562,9 @@ public final class MetaDataProtos {
if (other.hasIfExists()) {
setIfExists(other.getIfExists());
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -7001,6 +7697,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 3;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 3;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional int32 clientVersion = 3;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 3;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000004;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 3;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:DropFunctionRequest)
}
@@ -7028,6 +7757,16 @@ public final class MetaDataProtos {
* <code>repeated bytes tableMetadataMutations = 1;</code>
*/
com.google.protobuf.ByteString getTableMetadataMutations(int index);
+
+ // optional int32 clientVersion = 2;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code UpdateIndexStateRequest}
@@ -7088,6 +7827,11 @@ public final class MetaDataProtos {
tableMetadataMutations_.add(input.readBytes());
break;
}
+ case 16: {
+ bitField0_ |= 0x00000001;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -7130,6 +7874,7 @@ public final class MetaDataProtos {
return PARSER;
}
+ private int bitField0_;
// repeated bytes tableMetadataMutations = 1;
public static final int TABLEMETADATAMUTATIONS_FIELD_NUMBER = 1;
private java.util.List<com.google.protobuf.ByteString> tableMetadataMutations_;
@@ -7153,8 +7898,25 @@ public final class MetaDataProtos {
return tableMetadataMutations_.get(index);
}
+ // optional int32 clientVersion = 2;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 2;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tableMetadataMutations_ = java.util.Collections.emptyList();
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -7171,6 +7933,9 @@ public final class MetaDataProtos {
for (int i = 0; i < tableMetadataMutations_.size(); i++) {
output.writeBytes(1, tableMetadataMutations_.get(i));
}
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeInt32(2, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -7189,6 +7954,10 @@ public final class MetaDataProtos {
size += dataSize;
size += 1 * getTableMetadataMutationsList().size();
}
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(2, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -7214,6 +7983,11 @@ public final class MetaDataProtos {
boolean result = true;
result = result && getTableMetadataMutationsList()
.equals(other.getTableMetadataMutationsList());
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -7231,6 +8005,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + TABLEMETADATAMUTATIONS_FIELD_NUMBER;
hash = (53 * hash) + getTableMetadataMutationsList().hashCode();
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -7342,6 +8120,8 @@ public final class MetaDataProtos {
super.clear();
tableMetadataMutations_ = java.util.Collections.emptyList();
bitField0_ = (bitField0_ & ~0x00000001);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
return this;
}
@@ -7369,11 +8149,17 @@ public final class MetaDataProtos {
public org.apache.phoenix.coprocessor.generated.MetaDataProtos.UpdateIndexStateRequest buildPartial() {
org.apache.phoenix.coprocessor.generated.MetaDataProtos.UpdateIndexStateRequest result = new org.apache.phoenix.coprocessor.generated.MetaDataProtos.UpdateIndexStateRequest(this);
int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
tableMetadataMutations_ = java.util.Collections.unmodifiableList(tableMetadataMutations_);
bitField0_ = (bitField0_ & ~0x00000001);
}
result.tableMetadataMutations_ = tableMetadataMutations_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.clientVersion_ = clientVersion_;
+ result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
@@ -7399,6 +8185,9 @@ public final class MetaDataProtos {
}
onChanged();
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -7498,6 +8287,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 2;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000002;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 2;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:UpdateIndexStateRequest)
}
@@ -7511,6 +8333,16 @@ public final class MetaDataProtos {
public interface ClearCacheRequestOrBuilder
extends com.google.protobuf.MessageOrBuilder {
+
+ // optional int32 clientVersion = 1;
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code ClearCacheRequest}
@@ -7545,6 +8377,7 @@ public final class MetaDataProtos {
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
initFields();
+ int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
@@ -7562,6 +8395,11 @@ public final class MetaDataProtos {
}
break;
}
+ case 8: {
+ bitField0_ |= 0x00000001;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -7601,7 +8439,25 @@ public final class MetaDataProtos {
return PARSER;
}
+ private int bitField0_;
+ // optional int32 clientVersion = 1;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 1;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -7615,6 +8471,9 @@ public final class MetaDataProtos {
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeInt32(1, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -7624,6 +8483,10 @@ public final class MetaDataProtos {
if (size != -1) return size;
size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(1, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -7647,6 +8510,11 @@ public final class MetaDataProtos {
org.apache.phoenix.coprocessor.generated.MetaDataProtos.ClearCacheRequest other = (org.apache.phoenix.coprocessor.generated.MetaDataProtos.ClearCacheRequest) obj;
boolean result = true;
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -7660,6 +8528,10 @@ public final class MetaDataProtos {
}
int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode();
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -7769,6 +8641,8 @@ public final class MetaDataProtos {
public Builder clear() {
super.clear();
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
return this;
}
@@ -7795,6 +8669,13 @@ public final class MetaDataProtos {
public org.apache.phoenix.coprocessor.generated.MetaDataProtos.ClearCacheRequest buildPartial() {
org.apache.phoenix.coprocessor.generated.MetaDataProtos.ClearCacheRequest result = new org.apache.phoenix.coprocessor.generated.MetaDataProtos.ClearCacheRequest(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.clientVersion_ = clientVersion_;
+ result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
@@ -7810,6 +8691,9 @@ public final class MetaDataProtos {
public Builder mergeFrom(org.apache.phoenix.coprocessor.generated.MetaDataProtos.ClearCacheRequest other) {
if (other == org.apache.phoenix.coprocessor.generated.MetaDataProtos.ClearCacheRequest.getDefaultInstance()) return this;
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -7835,6 +8719,40 @@ public final class MetaDataProtos {
}
return this;
}
+ private int bitField0_;
+
+ // optional int32 clientVersion = 1;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000001;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
// @@protoc_insertion_point(builder_scope:ClearCacheRequest)
}
@@ -8187,6 +9105,16 @@ public final class MetaDataProtos {
public interface GetVersionRequestOrBuilder
extends com.google.protobuf.MessageOrBuilder {
+
+ // optional int32 clientVersion = 1;
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code GetVersionRequest}
@@ -8221,6 +9149,7 @@ public final class MetaDataProtos {
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
initFields();
+ int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
@@ -8238,6 +9167,11 @@ public final class MetaDataProtos {
}
break;
}
+ case 8: {
+ bitField0_ |= 0x00000001;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -8277,7 +9211,25 @@ public final class MetaDataProtos {
return PARSER;
}
+ private int bitField0_;
+ // optional int32 clientVersion = 1;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 1;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -8291,6 +9243,9 @@ public final class MetaDataProtos {
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeInt32(1, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -8300,6 +9255,10 @@ public final class MetaDataProtos {
if (size != -1) return size;
size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(1, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -8323,6 +9282,11 @@ public final class MetaDataProtos {
org.apache.phoenix.coprocessor.generated.MetaDataProtos.GetVersionRequest other = (org.apache.phoenix.coprocessor.generated.MetaDataProtos.GetVersionRequest) obj;
boolean result = true;
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -8336,6 +9300,10 @@ public final class MetaDataProtos {
}
int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode();
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -8445,6 +9413,8 @@ public final class MetaDataProtos {
public Builder clear() {
super.clear();
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
return this;
}
@@ -8471,6 +9441,13 @@ public final class MetaDataProtos {
public org.apache.phoenix.coprocessor.generated.MetaDataProtos.GetVersionRequest buildPartial() {
org.apache.phoenix.coprocessor.generated.MetaDataProtos.GetVersionRequest result = new org.apache.phoenix.coprocessor.generated.MetaDataProtos.GetVersionRequest(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.clientVersion_ = clientVersion_;
+ result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
@@ -8486,6 +9463,9 @@ public final class MetaDataProtos {
public Builder mergeFrom(org.apache.phoenix.coprocessor.generated.MetaDataProtos.GetVersionRequest other) {
if (other == org.apache.phoenix.coprocessor.generated.MetaDataProtos.GetVersionRequest.getDefaultInstance()) return this;
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -8511,6 +9491,40 @@ public final class MetaDataProtos {
}
return this;
}
+ private int bitField0_;
+
+ // optional int32 clientVersion = 1;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000001;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 1;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
// @@protoc_insertion_point(builder_scope:GetVersionRequest)
}
@@ -9007,6 +10021,16 @@ public final class MetaDataProtos {
* <code>required int64 clientTimestamp = 4;</code>
*/
long getClientTimestamp();
+
+ // optional int32 clientVersion = 5;
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ boolean hasClientVersion();
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ int getClientVersion();
}
/**
* Protobuf type {@code ClearTableFromCacheRequest}
@@ -9079,6 +10103,11 @@ public final class MetaDataProtos {
clientTimestamp_ = input.readInt64();
break;
}
+ case 40: {
+ bitField0_ |= 0x00000010;
+ clientVersion_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -9183,11 +10212,28 @@ public final class MetaDataProtos {
return clientTimestamp_;
}
+ // optional int32 clientVersion = 5;
+ public static final int CLIENTVERSION_FIELD_NUMBER = 5;
+ private int clientVersion_;
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+
private void initFields() {
tenantId_ = com.google.protobuf.ByteString.EMPTY;
schemaName_ = com.google.protobuf.ByteString.EMPTY;
tableName_ = com.google.protobuf.ByteString.EMPTY;
clientTimestamp_ = 0L;
+ clientVersion_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -9229,6 +10275,9 @@ public final class MetaDataProtos {
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeInt64(4, clientTimestamp_);
}
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeInt32(5, clientVersion_);
+ }
getUnknownFields().writeTo(output);
}
@@ -9254,6 +10303,10 @@ public final class MetaDataProtos {
size += com.google.protobuf.CodedOutputStream
.computeInt64Size(4, clientTimestamp_);
}
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(5, clientVersion_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -9297,6 +10350,11 @@ public final class MetaDataProtos {
result = result && (getClientTimestamp()
== other.getClientTimestamp());
}
+ result = result && (hasClientVersion() == other.hasClientVersion());
+ if (hasClientVersion()) {
+ result = result && (getClientVersion()
+ == other.getClientVersion());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -9326,6 +10384,10 @@ public final class MetaDataProtos {
hash = (37 * hash) + CLIENTTIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + hashLong(getClientTimestamp());
}
+ if (hasClientVersion()) {
+ hash = (37 * hash) + CLIENTVERSION_FIELD_NUMBER;
+ hash = (53 * hash) + getClientVersion();
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -9443,6 +10505,8 @@ public final class MetaDataProtos {
bitField0_ = (bitField0_ & ~0x00000004);
clientTimestamp_ = 0L;
bitField0_ = (bitField0_ & ~0x00000008);
+ clientVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@@ -9487,6 +10551,10 @@ public final class MetaDataProtos {
to_bitField0_ |= 0x00000008;
}
result.clientTimestamp_ = clientTimestamp_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.clientVersion_ = clientVersion_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -9515,6 +10583,9 @@ public final class MetaDataProtos {
if (other.hasClientTimestamp()) {
setClientTimestamp(other.getClientTimestamp());
}
+ if (other.hasClientVersion()) {
+ setClientVersion(other.getClientVersion());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -9699,6 +10770,39 @@ public final class MetaDataProtos {
return this;
}
+ // optional int32 clientVersion = 5;
+ private int clientVersion_ ;
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public boolean hasClientVersion() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public int getClientVersion() {
+ return clientVersion_;
+ }
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public Builder setClientVersion(int value) {
+ bitField0_ |= 0x00000010;
+ clientVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 clientVersion = 5;</code>
+ */
+ public Builder clearClientVersion() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ clientVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:ClearTableFromCacheRequest)
}
@@ -11156,60 +12260,67 @@ public final class MetaDataProtos {
"onTime\030\002 \001(\003\022\026\n\005table\030\003 \001(\0132\007.PTable\022\026\n\016" +
"tablesToDelete\030\004 \003(\014\022\022\n\ncolumnName\030\005 \001(\014" +
"\022\022\n\nfamilyName\030\006 \001(\014\022\024\n\014functionName\030\007 \001" +
- "(\014\022\034\n\010function\030\010 \003(\0132\n.PFunction\"{\n\017GetT" +
- "ableRequest\022\020\n\010tenantId\030\001 \002(\014\022\022\n\nschemaN" +
- "ame\030\002 \002(\014\022\021\n\ttableName\030\003 \002(\014\022\026\n\016tableTim" +
- "estamp\030\004 \002(\003\022\027\n\017clientTimestamp\030\005 \002(\003\"s\n",
- "\023GetFunctionsRequest\022\020\n\010tenantId\030\001 \002(\014\022\025" +
- "\n\rfunctionNames\030\002 \003(\014\022\032\n\022functionTimesta" +
- "mps\030\003 \003(\003\022\027\n\017clientTimestamp\030\004 \002(\003\"4\n\022Cr" +
- "eateTableRequest\022\036\n\026tableMetadataMutatio" +
- "ns\030\001 \003(\014\"[\n\025CreateFunctionRequest\022\036\n\026tab" +
- "leMetadataMutations\030\001 \003(\014\022\021\n\ttemporary\030\002" +
- " \002(\010\022\017\n\007replace\030\003 \001(\010\"V\n\020DropTableReques" +
- "t\022\036\n\026tableMetadataMutations\030\001 \003(\014\022\021\n\ttab" +
- "leType\030\002 \002(\t\022\017\n\007cascade\030\003 \001(\010\"2\n\020AddColu" +
- "mnRequest\022\036\n\026tableMetadataMutations\030\001 \003(",
- "\014\"3\n\021DropColumnRequest\022\036\n\026tableMetadataM" +
- "utations\030\001 \003(\014\"G\n\023DropFunctionRequest\022\036\n" +
- "\026tableMetadataMutations\030\001 \003(\014\022\020\n\010ifExist" +
- "s\030\002 \001(\010\"9\n\027UpdateIndexStateRequest\022\036\n\026ta" +
- "bleMetadataMutations\030\001 \003(\014\"\023\n\021ClearCache" +
- "Request\"\024\n\022ClearCacheResponse\"\023\n\021GetVers" +
- "ionRequest\"%\n\022GetVersionResponse\022\017\n\007vers" +
- "ion\030\001 \002(\003\"n\n\032ClearTableFromCacheRequest\022" +
- "\020\n\010tenantId\030\001 \002(\014\022\022\n\nschemaName\030\002 \002(\014\022\021\n" +
- "\ttableName\030\003 \002(\014\022\027\n\017clientTimestamp\030\004 \002(",
- "\003\"\035\n\033ClearTableFromCacheResponse*\365\002\n\014Mut" +
- "ationCode\022\030\n\024TABLE_ALREADY_EXISTS\020\000\022\023\n\017T" +
- "ABLE_NOT_FOUND\020\001\022\024\n\020COLUMN_NOT_FOUND\020\002\022\031" +
- "\n\025COLUMN_ALREADY_EXISTS\020\003\022\035\n\031CONCURRENT_" +
- "TABLE_MUTATION\020\004\022\027\n\023TABLE_NOT_IN_REGION\020" +
- "\005\022\025\n\021NEWER_TABLE_FOUND\020\006\022\034\n\030UNALLOWED_TA" +
- "BLE_MUTATION\020\007\022\021\n\rNO_PK_COLUMNS\020\010\022\032\n\026PAR" +
- "ENT_TABLE_NOT_FOUND\020\t\022\033\n\027FUNCTION_ALREAD" +
- "Y_EXISTS\020\n\022\026\n\022FUNCTION_NOT_FOUND\020\013\022\030\n\024NE" +
- "WER_FUNCTION_FOUND\020\014\022\032\n\026FUNCTION_NOT_IN_",
- "REGION\020\r2\304\005\n\017MetaDataService\022/\n\010getTable" +
- "\022\020.GetTableRequest\032\021.MetaDataResponse\0227\n" +
- "\014getFunctions\022\024.GetFunctionsRequest\032\021.Me" +
- "taDataResponse\0225\n\013createTable\022\023.CreateTa" +
- "bleRequest\032\021.MetaDataResponse\022;\n\016createF" +
- "unction\022\026.CreateFunctionRequest\032\021.MetaDa" +
- "taResponse\0221\n\tdropTable\022\021.DropTableReque" +
- "st\032\021.MetaDataResponse\0227\n\014dropFunction\022\024." +
- "DropFunctionRequest\032\021.MetaDataResponse\0221" +
- "\n\taddColumn\022\021.AddColumnRequest\032\021.MetaDat",
- "aResponse\0223\n\ndropColumn\022\022.DropColumnRequ" +
- "est\032\021.MetaDataResponse\022?\n\020updateIndexSta" +
- "te\022\030.UpdateIndexStateRequest\032\021.MetaDataR" +
- "esponse\0225\n\nclearCache\022\022.ClearCacheReques" +
- "t\032\023.ClearCacheResponse\0225\n\ngetVersion\022\022.G" +
- "etVersionRequest\032\023.GetVersionResponse\022P\n" +
- "\023clearTableFromCache\022\033.ClearTableFromCac" +
- "heRequest\032\034.ClearTableFromCacheResponseB" +
- "B\n(org.apache.phoenix.coprocessor.genera" +
- "tedB\016MetaDataProtosH\001\210\001\001\240\001\001"
+ "(\014\022\034\n\010function\030\010 \003(\0132\n.PFunction\"\222\001\n\017Get" +
+ "TableRequest\022\020\n\010tenantId\030\001 \002(\014\022\022\n\nschema" +
+ "Name\030\002 \002(\014\022\021\n\ttableName\030\003 \002(\014\022\026\n\016tableTi" +
+ "mestamp\030\004 \002(\003\022\027\n\017clientTimestamp\030\005 \002(\003\022\025",
+ "\n\rclientVersion\030\006 \001(\005\"\212\001\n\023GetFunctionsRe" +
+ "quest\022\020\n\010tenantId\030\001 \002(\014\022\025\n\rfunctionNames" +
+ "\030\002 \003(\014\022\032\n\022functionTimestamps\030\003 \003(\003\022\027\n\017cl" +
+ "ientTimestamp\030\004 \002(\003\022\025\n\rclientVersion\030\005 \001" +
+ "(\005\"K\n\022CreateTableRequest\022\036\n\026tableMetadat" +
+ "aMutations\030\001 \003(\014\022\025\n\rclientVersion\030\002 \001(\005\"" +
+ "r\n\025CreateFunctionRequest\022\036\n\026tableMetadat" +
+ "aMutations\030\001 \003(\014\022\021\n\ttemporary\030\002 \002(\010\022\017\n\007r" +
+ "eplace\030\003 \001(\010\022\025\n\rclientVersion\030\004 \001(\005\"m\n\020D" +
+ "ropTableRequest\022\036\n\026tableMetadataMutation",
+ "s\030\001 \003(\014\022\021\n\ttableType\030\002 \002(\t\022\017\n\007cascade\030\003 " +
+ "\001(\010\022\025\n\rclientVersion\030\004 \001(\005\"I\n\020AddColumnR" +
+ "equest\022\036\n\026tableMetadataMutations\030\001 \003(\014\022\025" +
+ "\n\rclientVersion\030\002 \001(\005\"J\n\021DropColumnReque" +
+ "st\022\036\n\026tableMetadataMutations\030\001 \003(\014\022\025\n\rcl" +
+ "ientVersion\030\002 \001(\005\"^\n\023DropFunctionRequest" +
+ "\022\036\n\026tableMetadataMutations\030\001 \003(\014\022\020\n\010ifEx" +
+ "ists\030\002 \001(\010\022\025\n\rclientVersion\030\003 \001(\005\"P\n\027Upd" +
+ "ateIndexStateRequest\022\036\n\026tableMetadataMut" +
+ "ations\030\001 \003(\014\022\025\n\rclientVersion\030\002 \001(\005\"*\n\021C",
+ "learCacheRequest\022\025\n\rclientVersion\030\001 \001(\005\"" +
+ "\024\n\022ClearCacheResponse\"*\n\021GetVersionReque" +
+ "st\022\025\n\rclientVersion\030\001 \001(\005\"%\n\022GetVersionR" +
+ "esponse\022\017\n\007version\030\001 \002(\003\"\205\001\n\032ClearTableF" +
+ "romCacheRequest\022\020\n\010tenantId\030\001 \002(\014\022\022\n\nsch" +
+ "emaName\030\002 \002(\014\022\021\n\ttableName\030\003 \002(\014\022\027\n\017clie" +
+ "ntTimestamp\030\004 \002(\003\022\025\n\rclientVersion\030\005 \001(\005" +
+ "\"\035\n\033ClearTableFromCacheResponse*\365\002\n\014Muta" +
+ "tionCode\022\030\n\024TABLE_ALREADY_EXISTS\020\000\022\023\n\017TA" +
+ "BLE_NOT_FOUND\020\001\022\024\n\020COLUMN_NOT_FOUND\020\002\022\031\n",
+ "\025COLUMN_ALREADY_EXISTS\020\003\022\035\n\031CONCURRENT_T" +
+ "ABLE_MUTATION\020\004\022\027\n\023TABLE_NOT_IN_REGION\020\005" +
+ "\022\025\n\021NEWER_TABLE_FOUND\020\006\022\034\n\030UNALLOWED_TAB" +
+ "LE_MUTATION\020\007\022\021\n\rNO_PK_COLUMNS\020\010\022\032\n\026PARE" +
+ "NT_TABLE_NOT_FOUND\020\t\022\033\n\027FUNCTION_ALREADY" +
+ "_EXISTS\020\n\022\026\n\022FUNCTION_NOT_FOUND\020\013\022\030\n\024NEW" +
+ "ER_FUNCTION_FOUND\020\014\022\032\n\026FUNCTION_NOT_IN_R" +
+ "EGION\020\r2\304\005\n\017MetaDataService\022/\n\010getTable\022" +
+ "\020.GetTableRequest\032\021.MetaDataResponse\0227\n\014" +
+ "getFunctions\022\024.GetFunctionsRequest\032\021.Met",
+ "aDataResponse\0225\n\013createTable\022\023.CreateTab" +
+ "leRequest\032\021.MetaDataResponse\022;\n\016createFu" +
+ "nction\022\026.CreateFunctionRequest\032\021.MetaDat" +
+ "aResponse\0221\n\tdropTable\022\021.DropTableReques" +
+ "t\032\021.MetaDataResponse\0227\n\014dropFunction\022\024.D" +
+ "ropFunctionRequest\032\021.MetaDataResponse\0221\n" +
+ "\taddColumn\022\021.AddColumnRequest\032\021.MetaData" +
+ "Response\0223\n\ndropColumn\022\022.DropColumnReque" +
+ "st\032\021.MetaDataResponse\022?\n\020updateIndexStat" +
+ "e\022\030.UpdateIndexStateRequest\032\021.MetaDataRe",
+ "sponse\0225\n\nclearCache\022\022.ClearCacheRequest" +
+ "\032\023.ClearCacheResponse\0225\n\ngetVersion\022\022.Ge" +
+ "tVersionRequest\032\023.GetVersionResponse\022P\n\023" +
+ "clearTableFromCache\022\033.ClearTableFromCach" +
+ "eRequest\032\034.ClearTableFromCacheResponseBB" +
+ "\n(org.apache.phoenix.coprocessor.generat" +
+ "edB\016MetaDataProtosH\001\210\001\001\240\001\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -11227,61 +12338,61 @@ public final class MetaDataProtos {
internal_static_GetTableRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_GetTableRequest_descriptor,
- new java.lang.String[] { "TenantId", "SchemaName", "TableName", "TableTimestamp", "ClientTimestamp", });
+ new java.lang.String[] { "TenantId", "SchemaName", "TableName", "TableTimestamp", "ClientTimestamp", "ClientVersion", });
internal_static_GetFunctionsRequest_descriptor =
getDescriptor().getMessageTypes().get(2);
internal_static_GetFunctionsRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_GetFunctionsRequest_descriptor,
- new java.lang.String[] { "TenantId", "FunctionNames", "FunctionTimestamps", "ClientTimestamp", });
+ new java.lang.String[] { "TenantId", "FunctionNames", "FunctionTimestamps", "ClientTimestamp", "ClientVersion", });
internal_static_CreateTableRequest_descriptor =
getDescriptor().getMessageTypes().get(3);
internal_static_CreateTableRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_CreateTableRequest_descriptor,
- new java.lang.String[] { "TableMetadataMutations", });
+ new java.lang.String[] { "TableMetadataMutations", "ClientVersion", });
internal_static_CreateFunctionRequest_descriptor =
getDescriptor().getMessageTypes().get(4);
internal_static_CreateFunctionRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_CreateFunctionRequest_descriptor,
- new java.lang.String[] { "TableMetadataMutations", "Temporary", "Replace", });
+ new java.lang.String[] { "TableMetadataMutations", "Temporary", "Replace", "ClientVersion", });
internal_static_DropTableRequest_descriptor =
getDescriptor().getMessageTypes().get(5);
internal_static_DropTableRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_DropTableRequest_descriptor,
- new java.lang.String[] { "TableMetadataMutations", "TableType", "Cascade", });
+ new java.lang.String[] { "TableMetadataMutations", "TableType", "Cascade", "ClientVersion", });
internal_static_AddColumnRequest_descriptor =
getDescriptor().getMessageTypes().get(6);
internal_static_AddColumnRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_AddColumnRequest_descriptor,
- new java.lang.String[] { "TableMetadataMutations", });
+ new java.lang.String[] { "TableMetadataMutations", "ClientVersion", });
internal_static_DropColumnRequest_descriptor =
getDescriptor().getMessageTypes().get(7);
internal_static_DropColumnRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_DropColumnRequest_descriptor,
- new java.lang.String[] { "TableMetadataMutations", });
+ new java.lang.String[] { "TableMetadataMutations", "ClientVersion", });
internal_static_DropFunctionRequest_descriptor =
getDescriptor().getMessageTypes().get(8);
internal_static_DropFunctionRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_DropFunctionRequest_descriptor,
- new java.lang.String[] { "TableMetadataMutations", "IfExists", });
+ new java.lang.String[] { "TableMetadataMutations", "IfExists", "ClientVersion", });
internal_static_UpdateIndexStateRequest_descriptor =
getDescriptor().getMessageTypes().get(9);
internal_static_UpdateIndexStateRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_UpdateIndexStateRequest_descriptor,
- new java.lang.String[] { "TableMetadataMutations", });
+ new java.lang.String[] { "TableMetadataMutations", "ClientVersion", });
internal_static_ClearCacheRequest_descriptor =
getDescriptor().getMessageTypes().get(10);
internal_static_ClearCacheRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_ClearCacheRequest_descriptor,
- new java.lang.String[] { });
+ new java.lang.String[] { "ClientVersion", });
internal_static_ClearCacheResponse_descriptor =
getDescriptor().getMessageTypes().get(11);
internal_static_ClearCacheResponse_fieldAccessorTable = new
@@ -11293,7 +12404,7 @@ public final class MetaDataProtos {
internal_static_GetVersionRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_GetVersionRequest_descriptor,
- new java.lang.String[] { });
+ new java.lang.String[] { "ClientVersion", });
internal_static_GetVersionResponse_descriptor =
getDescriptor().getMessageTypes().get(13);
internal_static_GetVersionResponse_fieldAccessorTable = new
@@ -11305,7 +12416,7 @@ public final class MetaDataProtos {
internal_static_ClearTableFromCacheRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_ClearTableFromCacheRequest_descriptor,
- new java.lang.String[] { "TenantId", "SchemaName", "TableName", "ClientTimestamp", });
+ new java.lang.String[] { "TenantId", "SchemaName", "TableName", "ClientTimestamp", "ClientVersion", });
internal_static_ClearTableFromCacheResponse_descriptor =
getDescriptor().getMessageTypes().get(15);
internal_static_ClearTableFromCacheResponse_fieldAccessorTable = new
[45/50] [abbrv] phoenix git commit: PHOENIX-2101 Implement
ARRAY_TO_STRING built in function (Dumindu Buddhika)
Posted by ma...@apache.org.
PHOENIX-2101 Implement ARRAY_TO_STRING built in function (Dumindu
Buddhika)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/236ce1c8
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/236ce1c8
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/236ce1c8
Branch: refs/heads/calcite
Commit: 236ce1c87c729c9beba5985e4fe3871e300176e6
Parents: 33d6050
Author: ramkrishna <ra...@gmail.com>
Authored: Thu Jul 16 21:20:36 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Thu Jul 16 21:20:36 2015 +0530
----------------------------------------------------------------------
.../end2end/ArrayToStringFunctionIT.java | 654 +++++++++++++++++++
.../phoenix/expression/ExpressionType.java | 4 +-
.../function/ArrayToStringFunction.java | 84 +++
.../phoenix/schema/types/PArrayDataType.java | 30 +
.../expression/ArrayToStringFunctionTest.java | 374 +++++++++++
5 files changed, 1145 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java
new file mode 100644
index 0000000..3b3f1d5
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java
@@ -0,0 +1,654 @@
+/*
+ * 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.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.*;
+
+import org.junit.Test;
+
+public class ArrayToStringFunctionIT extends BaseHBaseManagedTimeIT {
+ private void initTables(Connection conn) throws Exception {
+ String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchars VARCHAR[],integers INTEGER[],doubles DOUBLE[],bigints BIGINT[],chars CHAR(15)[],double1 DOUBLE,varchar1 VARCHAR,nullcheck INTEGER,chars2 CHAR(15)[])";
+ conn.createStatement().execute(ddl);
+ String dml = "UPSERT INTO regions(region_name,varchars,integers,doubles,bigints,chars,double1,varchar1,nullcheck,chars2) VALUES('SF Bay Area'," +
+ "ARRAY['2345','46345','23234']," +
+ "ARRAY[2345,46345,23234,456]," +
+ "ARRAY[23.45,46.345,23.234,45.6,5.78]," +
+ "ARRAY[12,34,56,78,910]," +
+ "ARRAY['a','bbbb','c','ddd','e']," +
+ "23.45," +
+ "', '," +
+ "NULL," +
+ "ARRAY['a','bbbb','c','ddd','e','foo']" +
+ ")";
+ PreparedStatement stmt = conn.prepareStatement(dml);
+ stmt.execute();
+ conn.commit();
+ }
+
+ @Test
+ public void testArrayToStringFunctionVarchar1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(varchars, ',','*') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "2345,46345,23234";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionVarchar2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(varchars, ',') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "2345,46345,23234";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionVarchar3() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['hello', 'hello'], ',') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "hello,hello";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionInt() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(integers, ',') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "2345,46345,23234,456";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionDouble1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(doubles, ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "23.45, 46.345, 23.234, 45.6, 5.78";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionDouble2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[2.3, 4.5], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "2.3, 4.5";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionBigint() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(bigints, ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "12, 34, 56, 78, 910";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionChar1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(chars, ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a , bbbb, c , ddd , e ";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionChar2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(chars2, ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a , bbbb, c , ddd , e , foo ";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionChar3() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(chars2, varchar1) FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a , bbbb, c , ddd , e , foo ";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNestedFunctions1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[integers[1],integers[1]], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "2345, 2345";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNestedFunctions2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[ARRAY_ELEM(ARRAY[2,4],1),ARRAY_ELEM(ARRAY[2,4],2)], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "2, 4";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNestedFunctions3() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[ARRAY_ELEM(doubles, 1), ARRAY_ELEM(doubles, 1)], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "23.45, 23.45";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNestedFunctions4() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_ELEM(ARRAY_APPEND(ARRAY['abc','bcd'], ARRAY_TO_STRING(ARRAY['a','b'], 'c')), 3) FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "acb";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithUpsert1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+
+ String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+ conn.createStatement().execute(ddl);
+
+ String dml = "UPSERT INTO regions(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY['hello','world'],','))";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT varchar FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "hello,world";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithUpsert2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+
+ String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+ conn.createStatement().execute(ddl);
+
+ String dml = "UPSERT INTO regions(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[3, 4, 5],', '))";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT varchar FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "3, 4, 5";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithUpsert3() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+
+ String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+ conn.createStatement().execute(ddl);
+
+ String dml = "UPSERT INTO regions(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[3.1, 4.2, 5.5],', '))";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT varchar FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "3.1, 4.2, 5.5";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithUpsert4() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+
+ String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+ conn.createStatement().execute(ddl);
+
+ String dml = "UPSERT INTO regions(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[true, false, true],', '))";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT varchar FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "true, false, true";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithUpsertSelect1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+
+ String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY,doubles DOUBLE[])";
+ conn.createStatement().execute(ddl);
+
+ ddl = "CREATE TABLE target (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+ conn.createStatement().execute(ddl);
+
+ String dml = "UPSERT INTO source(region_name,doubles) VALUES('SF Bay Area', ARRAY[5.67, 7.87])";
+ conn.createStatement().execute(dml);
+
+ dml = "UPSERT INTO source(region_name,doubles) VALUES('SF Bay Area2', ARRAY[9.2, 3.4])";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ dml = "UPSERT INTO target(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(doubles, ', ') FROM source";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT varchar FROM target");
+ assertTrue(rs.next());
+
+ String expected = "5.67, 7.87";
+ assertEquals(expected, rs.getString(1));
+ assertTrue(rs.next());
+
+ expected = "9.2, 3.4";
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithUpsertSelect2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+
+ String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY,varchars VARCHAR[])";
+ conn.createStatement().execute(ddl);
+
+ ddl = "CREATE TABLE target (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+ conn.createStatement().execute(ddl);
+
+ String dml = "UPSERT INTO source(region_name,varchars) VALUES('SF Bay Area', ARRAY['hello', '-)'])";
+ conn.createStatement().execute(dml);
+
+ dml = "UPSERT INTO source(region_name,varchars) VALUES('SF Bay Area2', ARRAY['hello', '-('])";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ dml = "UPSERT INTO target(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(varchars, ':') FROM source";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT varchar FROM target");
+ assertTrue(rs.next());
+
+ String expected = "hello:-)";
+ assertEquals(expected, rs.getString(1));
+ assertTrue(rs.next());
+
+ expected = "hello:-(";
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithUpsertSelect3() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+
+ String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY,booleans BOOLEAN[])";
+ conn.createStatement().execute(ddl);
+
+ ddl = "CREATE TABLE target (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+ conn.createStatement().execute(ddl);
+
+ String dml = "UPSERT INTO source(region_name, booleans) VALUES('SF Bay Area', ARRAY[true, true])";
+ conn.createStatement().execute(dml);
+
+ dml = "UPSERT INTO source(region_name, booleans) VALUES('SF Bay Area2', ARRAY[false, false])";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ dml = "UPSERT INTO target(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(booleans, ', ') FROM source";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT varchar FROM target");
+ assertTrue(rs.next());
+
+ String expected = "true, true";
+ assertEquals(expected, rs.getString(1));
+ assertTrue(rs.next());
+
+ expected = "false, false";
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionInWhere1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE '2345,46345,23234,456' = ARRAY_TO_STRING(integers,',')");
+ assertTrue(rs.next());
+
+ assertEquals("SF Bay Area", rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionInWhere2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'a,b,c' = ARRAY_TO_STRING(ARRAY['a', 'b', 'c'], ',')");
+ assertTrue(rs.next());
+
+ assertEquals("SF Bay Area", rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionInWhere3() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE '1.1,2.2,3.3' = ARRAY_TO_STRING(ARRAY[1.1, 2.2, 3.3], ',')");
+ assertTrue(rs.next());
+
+ assertEquals("SF Bay Area", rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionInWhere4() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'true,true,true' = ARRAY_TO_STRING(ARRAY[true, true, true], ',')");
+ assertTrue(rs.next());
+
+ assertEquals("SF Bay Area", rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionInWhere5() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'a, bbbb, c, ddd, e' = ARRAY_TO_STRING(ARRAY['a', 'bbbb', 'c' , 'ddd', 'e'], ', ')");
+ assertTrue(rs.next());
+
+ assertEquals("SF Bay Area", rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionInWhere6() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY_TO_STRING(ARRAY[1,2,3], varchar1) = '1, 2, 3'");
+ assertTrue(rs.next());
+
+ assertEquals("SF Bay Area", rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionInWhere7() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY_TO_STRING(varchars, varchar1) = '2345, 46345, 23234'");
+ assertTrue(rs.next());
+
+ assertEquals("SF Bay Area", rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNulls1() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['a', NULL, 'b'], ', ','*') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a, *, b";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNulls2() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['a', NULL, 'b'], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a, b";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNulls3() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[NULL, 'a', 'b'], ', ', '*') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "*, a, b";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNulls4() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[NULL, 'a', 'b'], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a, b";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNulls5() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['a', 'b', NULL], ', ', '*') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a, b, *";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNulls6() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['a', 'b', NULL], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a, b";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNulls7() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[NULL, NULL, 'a', 'b', NULL, 'c', 'd', NULL, 'e', NULL, NULL], ', ', '*') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "*, *, a, b, *, c, d, *, e, *, *";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testArrayToStringFunctionWithNulls8() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ initTables(conn);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[NULL, NULL, 'a', 'b', NULL, 'c', 'd', NULL, 'e', NULL, NULL], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+ assertTrue(rs.next());
+
+ String expected = "a, b, c, d, e";
+
+ assertEquals(expected, rs.getString(1));
+ assertFalse(rs.next());
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
index ef14e6a..3c364c0 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
@@ -29,6 +29,7 @@ import org.apache.phoenix.expression.function.ArrayFillFunction;
import org.apache.phoenix.expression.function.ArrayIndexFunction;
import org.apache.phoenix.expression.function.ArrayLengthFunction;
import org.apache.phoenix.expression.function.ArrayPrependFunction;
+import org.apache.phoenix.expression.function.ArrayToStringFunction;
import org.apache.phoenix.expression.function.ByteBasedRegexpReplaceFunction;
import org.apache.phoenix.expression.function.ByteBasedRegexpSplitFunction;
import org.apache.phoenix.expression.function.ByteBasedRegexpSubstrFunction;
@@ -249,7 +250,8 @@ public enum ExpressionType {
ExpFunction(ExpFunction.class),
PowerFunction(PowerFunction.class),
ArrayConcatFunction(ArrayConcatFunction.class),
- ArrayFillFunction(ArrayFillFunction.class)
+ ArrayFillFunction(ArrayFillFunction.class),
+ ArrayToStringFunction(ArrayToStringFunction.class)
;
ExpressionType(Class<? extends Expression> clazz) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayToStringFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayToStringFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayToStringFunction.java
new file mode 100644
index 0000000..9102df4
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayToStringFunction.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.expression.function;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.*;
+
+@FunctionParseNode.BuiltInFunction(name = ArrayToStringFunction.NAME, args = {
+ @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class}),
+ @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}),
+ @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}, defaultValue = "null")})
+public class ArrayToStringFunction extends ScalarFunction {
+ public static final String NAME = "ARRAY_TO_STRING";
+
+ public ArrayToStringFunction() {
+ }
+
+ public ArrayToStringFunction(List<Expression> children) {
+ super(children);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ Expression delimiterExpr = children.get(1);
+ if (!delimiterExpr.evaluate(tuple, ptr)) {
+ return false;
+ } else if (ptr.getLength() == 0) {
+ return true;
+ }
+ String delimiter = (String) delimiterExpr.getDataType().toObject(ptr, delimiterExpr.getSortOrder(), delimiterExpr.getMaxLength(), delimiterExpr.getScale());
+
+ Expression arrayExpr = children.get(0);
+ if (!arrayExpr.evaluate(tuple, ptr)) {
+ return false;
+ } else if (ptr.getLength() == 0) {
+ return true;
+ }
+ PhoenixArray array = (PhoenixArray) arrayExpr.getDataType().toObject(ptr, arrayExpr.getSortOrder(), arrayExpr.getMaxLength(), arrayExpr.getScale());
+
+ Expression nullExpr = children.get(2);
+ String nullString = null;
+ if (nullExpr.evaluate(tuple, ptr) && ptr.getLength() != 0) {
+ nullString = (String) nullExpr.getDataType().toObject(ptr, nullExpr.getSortOrder(), nullExpr.getMaxLength(), nullExpr.getScale());
+ }
+
+ return PArrayDataType.arrayToString(ptr, array, delimiter, nullString, getSortOrder());
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PVarchar.INSTANCE;
+ }
+
+ @Override
+ public SortOrder getSortOrder() {
+ return children.get(0).getSortOrder();
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
index 9ca64c5..bad02e4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
@@ -957,6 +957,36 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
return true;
}
+ public static boolean arrayToString(ImmutableBytesWritable ptr, PhoenixArray array, String delimiter, String nullString, SortOrder sortOrder) {
+ StringBuilder result = new StringBuilder();
+ boolean delimiterPending = false;
+ for (int i = 0; i < array.getDimensions() - 1; i++) {
+ Object element = array.getElement(i);
+ if (element == null) {
+ if (nullString != null) {
+ result.append(nullString);
+ }
+ } else {
+ result.append(element.toString());
+ delimiterPending = true;
+ }
+ if (nullString != null || (array.getElement(i + 1) != null && delimiterPending)) {
+ result.append(delimiter);
+ delimiterPending = false;
+ }
+ }
+ Object element = array.getElement(array.getDimensions() - 1);
+ if (element == null) {
+ if (nullString != null) {
+ result.append(nullString);
+ }
+ } else {
+ result.append(element.toString());
+ }
+ ptr.set(PVarchar.INSTANCE.toBytes(result.toString(), sortOrder));
+ return true;
+ }
+
public static int serailizeOffsetArrayIntoStream(DataOutputStream oStream, TrustedByteArrayOutputStream byteStream,
int noOfElements, int maxOffset, int[] offsetPos) throws IOException {
int offsetPosition = (byteStream.size());
http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
new file mode 100644
index 0000000..92eb6b5
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
@@ -0,0 +1,374 @@
+/*
+ * 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.expression;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.ArrayToStringFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.*;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class ArrayToStringFunctionTest {
+
+ private static void testExpression(LiteralExpression array, LiteralExpression delimiter, LiteralExpression nullString, String expected)
+ throws SQLException {
+ List<Expression> expressions = Lists.newArrayList((Expression) array);
+ expressions.add(delimiter);
+ expressions.add(nullString);
+
+ Expression arrayToStringFunction = new ArrayToStringFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayToStringFunction.evaluate(null, ptr);
+ String result = (String) arrayToStringFunction.getDataType().toObject(ptr, arrayToStringFunction.getSortOrder(), arrayToStringFunction.getMaxLength(), arrayToStringFunction.getScale());
+ assertEquals(expected, result);
+ }
+
+ private static void test(PhoenixArray array, PDataType arrayDataType, Integer arrMaxLen, Integer arrScale, String delimiter, String nullString, String expected, SortOrder arraySortOrder, SortOrder delimiterSortOrder, SortOrder nullStringSortOrder) throws SQLException {
+ LiteralExpression arrayLiteral, delimiterLiteral, nullStringLiteral;
+ arrayLiteral = LiteralExpression.newConstant(array, arrayDataType, arrMaxLen, arrScale, arraySortOrder, Determinism.ALWAYS);
+ delimiterLiteral = LiteralExpression.newConstant(delimiter, PVarchar.INSTANCE, null, null, delimiterSortOrder, Determinism.ALWAYS);
+ nullStringLiteral = LiteralExpression.newConstant(nullString, PVarchar.INSTANCE, null, null, nullStringSortOrder, Determinism.ALWAYS);
+ testExpression(arrayLiteral, delimiterLiteral, nullStringLiteral, expected);
+ }
+
+ @Test
+ public void testInt1() throws SQLException {
+ PDataType type = PIntegerArray.INSTANCE;
+ PDataType base = PInteger.INSTANCE;
+ Object[] o1 = new Object[]{1, 2, 3, 4, 5};
+ PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "1,2,3,4,5";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testInt2() throws SQLException {
+ PDataType type = PIntegerArray.INSTANCE;
+ PDataType base = PInteger.INSTANCE;
+ Object[] o1 = new Object[]{1, 2, 3, 4, 5};
+ PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "";
+ String expected = "1,2,3,4,5";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testInt3() throws SQLException {
+ PDataType type = PIntegerArray.INSTANCE;
+ PDataType base = PInteger.INSTANCE;
+ Object[] o1 = new Object[]{1, 2, 3, 4, 5};
+ PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(base, o1);
+ String delimiter = "";
+ String nullString = "";
+ String expected = null;
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testInt4() throws SQLException {
+ PDataType type = PIntegerArray.INSTANCE;
+ PDataType base = PInteger.INSTANCE;
+ Object[] o1 = new Object[]{1};
+ PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "";
+ String expected = "1";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testFloat1() throws SQLException {
+ PDataType type = PFloatArray.INSTANCE;
+ PDataType base = PFloat.INSTANCE;
+ Object[] o1 = new Object[]{(float) 1.1, (float) 2.2, (float) 3.3, (float) 4.4, (float) 5.5};
+ PhoenixArray arr = new PhoenixArray.PrimitiveFloatPhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "1.1,2.2,3.3,4.4,5.5";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testFloat2() throws SQLException {
+ PDataType type = PFloatArray.INSTANCE;
+ PDataType base = PFloat.INSTANCE;
+ Object[] o1 = new Object[]{(float) 1.1, (float) 2.2, (float) 3.3, (float) 4.4, (float) 5.5};
+ PhoenixArray arr = new PhoenixArray.PrimitiveFloatPhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "*";
+ String expected = "1.1, 2.2, 3.3, 4.4, 5.5";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testDate() throws SQLException {
+ PDataType type = PDateArray.INSTANCE;
+ PDataType base = PDate.INSTANCE;
+ Object[] o1 = new Object[]{new Date(0l), new Date(0l), new Date(0l)};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "*";
+ String expected = "1970-01-01, 1970-01-01, 1970-01-01";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testTime() throws SQLException {
+ PDataType type = PTimeArray.INSTANCE;
+ PDataType base = PTime.INSTANCE;
+ Object[] o1 = new Object[]{new Time(0l), new Time(0l), new Time(0l)};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "*";
+ String expected = "";
+ for (int i = 0; i < o1.length - 1; i++) {
+ expected += o1[i].toString() + ", ";
+ }
+ expected += o1[o1.length - 1];
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testTimestamp() throws SQLException {
+ PDataType type = PTimestampArray.INSTANCE;
+ PDataType base = PTimestamp.INSTANCE;
+ Object[] o1 = new Object[]{new Timestamp(0l), new Timestamp(0l), new Timestamp(0l)};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "*";
+ String expected = "";
+ for (int i = 0; i < o1.length - 1; i++) {
+ expected += o1[i].toString() + ", ";
+ }
+ expected += o1[o1.length - 1];
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testVarchar1() throws SQLException {
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+ Object[] o1 = new Object[]{"hello", null, "hello", null};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "*";
+ String expected = "hello, *, hello, *";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testVarchar2() throws SQLException {
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+ Object[] o1 = new Object[]{"hello", null, "hello", null, null};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "*";
+ String expected = "hello, *, hello, *, *";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testVarchar3() throws SQLException {
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+ Object[] o1 = new Object[]{"hello", null, "hello", null, null};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "";
+ String expected = "hello, hello";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testVarchar4() throws SQLException {
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+ Object[] o1 = new Object[]{null, "hello", "hello", null, null};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "";
+ String expected = "hello, hello";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testVarchar5() throws SQLException {
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+ Object[] o1 = new Object[]{"hello"};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "";
+ String expected = "hello";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testVarchar6() throws SQLException {
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+ Object[] o1 = new Object[]{null, null, null, null, "hello"};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "";
+ String expected = "hello";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testVarchar7() throws SQLException {
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+ Object[] o1 = new Object[]{null, null, null, null, "hello"};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ", ";
+ String nullString = "*";
+ String expected = "*, *, *, *, hello";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testDouble() throws SQLException {
+ PDataType type = PDoubleArray.INSTANCE;
+ PDataType base = PDouble.INSTANCE;
+ Object[] o1 = new Object[]{23.4, 56.8, 2.4};
+ PhoenixArray arr = new PhoenixArray.PrimitiveDoublePhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "23.4,56.8,2.4";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testTinyint() throws SQLException {
+ PDataType type = PTinyintArray.INSTANCE;
+ PDataType base = PTinyint.INSTANCE;
+ Object[] o1 = new Object[]{(byte) 2, (byte) 4, (byte) 5};
+ PhoenixArray arr = new PhoenixArray.PrimitiveBytePhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "2,4,5";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testSmallint() throws SQLException {
+ PDataType type = PSmallintArray.INSTANCE;
+ PDataType base = PSmallint.INSTANCE;
+ Object[] o1 = new Object[]{(short) 6, (short) 7, (short) 8};
+ PhoenixArray arr = new PhoenixArray.PrimitiveShortPhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "6,7,8";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testBoolean() throws SQLException {
+ PDataType type = PBooleanArray.INSTANCE;
+ PDataType base = PBoolean.INSTANCE;
+ Object[] o1 = new Object[]{true, false, true};
+ PhoenixArray arr = new PhoenixArray.PrimitiveBooleanPhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "true,false,true";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testLong() throws SQLException {
+ PDataType type = PLongArray.INSTANCE;
+ PDataType base = PLong.INSTANCE;
+ Object[] o1 = new Object[]{(long) 23, (long) 34, (long) 45};
+ PhoenixArray arr = new PhoenixArray.PrimitiveLongPhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "23,34,45";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testDecimal1() throws SQLException {
+ PDataType type = PDecimalArray.INSTANCE;
+ PDataType base = PDecimal.INSTANCE;
+ Object[] o1 = new Object[]{BigDecimal.valueOf(23.45), BigDecimal.valueOf(2.345), BigDecimal.valueOf(234.5)};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "23.45,2.345,234.5";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testDecimal2() throws SQLException {
+ PDataType type = PDecimalArray.INSTANCE;
+ PDataType base = PDecimal.INSTANCE;
+ Object[] o1 = new Object[]{BigDecimal.valueOf(23.45), BigDecimal.valueOf(2.345), BigDecimal.valueOf(234.5), null};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "23.45,2.345,234.5,*";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testDecimal3() throws SQLException {
+ PDataType type = PDecimalArray.INSTANCE;
+ PDataType base = PDecimal.INSTANCE;
+ Object[] o1 = new Object[]{BigDecimal.valueOf(23.45), BigDecimal.valueOf(2.345), null, BigDecimal.valueOf(234.5)};
+ PhoenixArray arr = new PhoenixArray(base, o1);
+ String delimiter = ",";
+ String nullString = "*";
+ String expected = "23.45,2.345,*,234.5";
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+ test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+ }
+}
[42/50] [abbrv] phoenix git commit: PHOENIX-2121 Fix flapping
RowValueConstructorIT
Posted by ma...@apache.org.
PHOENIX-2121 Fix flapping RowValueConstructorIT
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/553d3ccf
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/553d3ccf
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/553d3ccf
Branch: refs/heads/calcite
Commit: 553d3ccf40fbef78de9d8b14e2b774d2a2fc6597
Parents: a8f0d76
Author: Samarth <sa...@salesforce.com>
Authored: Wed Jul 15 12:48:55 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Wed Jul 15 12:48:55 2015 -0700
----------------------------------------------------------------------
.../phoenix/end2end/RowValueConstructorIT.java | 46 +++++++++++---------
1 file changed, 25 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/553d3ccf/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
index e5cfeb0..5bf0a1e 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
@@ -1430,21 +1430,22 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
@Test
public void testCountDistinct1() throws Exception {
Connection conn = nextConnection(getUrl());
- String ddl = "CREATE TABLE regions1 (region_name VARCHAR PRIMARY KEY, a INTEGER, b INTEGER)";
+ String tableName = "testCountDistinct1rvc";
+ String ddl = "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY, a INTEGER, b INTEGER)";
conn.createStatement().execute(ddl);
conn = nextConnection(getUrl());
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('a', 6,3)");
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('a', 6,3)");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('b', 2,4)");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('b', 2,4)");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions1(region_name, a, b) VALUES('c', 6,3)");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('c', 6,3)");
stmt.execute();
conn.commit();
conn = nextConnection(getUrl());
ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions1");
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from " + tableName);
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
conn.close();
@@ -1453,22 +1454,23 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
@Test
public void testCountDistinct2() throws Exception {
Connection conn = nextConnection(getUrl());
- String ddl = "CREATE TABLE regions2 (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
+ String tableName = "testCountDistinct2rvc";
+ String ddl = "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
conn.createStatement().execute(ddl);
conn.commit();
conn = nextConnection(getUrl());
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('a', 'fooo','abc')");
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('a', 'fooo','abc')");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('b', 'off','bac')");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('b', 'off','bac')");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions2(region_name, a, b) VALUES('c', 'fooo', 'abc')");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('c', 'fooo', 'abc')");
stmt.execute();
conn.commit();
conn = nextConnection(getUrl());
ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions2");
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from " + tableName);
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
}
@@ -1476,23 +1478,24 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
@Test
public void testCountDistinct3() throws Exception {
Connection conn = nextConnection(getUrl());
- String ddl = "CREATE TABLE regions3 (region_name VARCHAR PRIMARY KEY, a Boolean, b Boolean)";
+ String tableName = "testCountDistinct3rvc";
+ String ddl = "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY, a Boolean, b Boolean)";
conn.createStatement().execute(ddl);
conn = nextConnection(getUrl());
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('a', true, true)");
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('a', true, true)");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('b', true, False)");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('b', true, False)");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('c', true, true)");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('c', true, true)");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions3(region_name, a, b) VALUES('d', true, false)");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('d', true, false)");
stmt.execute();
conn.commit();
conn = nextConnection(getUrl());
ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions3");
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from " + tableName);
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
}
@@ -1500,21 +1503,22 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
@Test
public void testCountDistinct4() throws Exception {
Connection conn = nextConnection(getUrl());
- String ddl = "CREATE TABLE regions4 (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
+ String tableName = "testCountDistinct4rvc";
+ String ddl = "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
conn.createStatement().execute(ddl);
conn = nextConnection(getUrl());
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('a', 'fooo','abc')");
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('a', 'fooo','abc')");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('b', 'off','bac')");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('b', 'off','bac')");
stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO regions4(region_name, a, b) VALUES('c', 'foo', 'abc')");
+ stmt = conn.prepareStatement("UPSERT INTO " + tableName + " (region_name, a, b) VALUES('c', 'foo', 'abc')");
stmt.execute();
conn.commit();
conn = nextConnection(getUrl());
ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from regions4");
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT (a,b)) from " + tableName);
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
}
[02/50] [abbrv] phoenix git commit: PHOENIX-2036 -
PhoenixConfigurationUtil should provide a pre-normalize table name to
PhoenixRuntime
Posted by ma...@apache.org.
PHOENIX-2036 - PhoenixConfigurationUtil should provide a pre-normalize table name to PhoenixRuntime
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/c398e182
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/c398e182
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/c398e182
Branch: refs/heads/calcite
Commit: c398e1823d8fe16c729e3b75eaf754eef0702856
Parents: be5aba5
Author: ravimagham <ra...@apache.org>
Authored: Sat Jul 4 10:08:00 2015 -0700
Committer: ravimagham <ra...@apache.org>
Committed: Sat Jul 4 10:08:00 2015 -0700
----------------------------------------------------------------------
.../util/PhoenixConfigurationUtilTest.java | 28 +++++++++++++--
.../org/apache/phoenix/util/QueryUtilTest.java | 36 ++++++++++++++++++--
2 files changed, 58 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c398e182/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java
index f8f2a63..aa03501 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtilTest.java
@@ -73,7 +73,29 @@ public class PhoenixConfigurationUtilTest extends BaseConnectionlessQueryTest {
configuration.set(HConstants.ZOOKEEPER_QUORUM, getUrl());
PhoenixConfigurationUtil.setInputTableName(configuration, tableName);
final String selectStatement = PhoenixConfigurationUtil.getSelectStatement(configuration);
- final String expectedSelectStatement = "SELECT \"A_STRING\",\"A_BINARY\",\"0\".\"COL1\" FROM " + SchemaUtil.getEscapedArgument(tableName) ;
+ final String expectedSelectStatement = "SELECT \"A_STRING\",\"A_BINARY\",\"0\".\"COL1\" FROM " + tableName ;
+ assertEquals(expectedSelectStatement, selectStatement);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectStatementWithSchema() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES));
+ final String tableName = "TEST_TABLE";
+ final String schemaName = SchemaUtil.getEscapedArgument("schema");
+ final String fullTableName = SchemaUtil.getTableName(schemaName, tableName);
+ try {
+ String ddl = "CREATE TABLE "+ fullTableName +
+ " (a_string varchar not null, a_binary varbinary not null, col1 integer" +
+ " CONSTRAINT pk PRIMARY KEY (a_string, a_binary))\n";
+ conn.createStatement().execute(ddl);
+ final Configuration configuration = new Configuration ();
+ configuration.set(HConstants.ZOOKEEPER_QUORUM, getUrl());
+ PhoenixConfigurationUtil.setInputTableName(configuration, fullTableName);
+ final String selectStatement = PhoenixConfigurationUtil.getSelectStatement(configuration);
+ final String expectedSelectStatement = "SELECT \"A_STRING\",\"A_BINARY\",\"0\".\"COL1\" FROM " + fullTableName;
assertEquals(expectedSelectStatement, selectStatement);
} finally {
conn.close();
@@ -94,7 +116,7 @@ public class PhoenixConfigurationUtilTest extends BaseConnectionlessQueryTest {
PhoenixConfigurationUtil.setInputTableName(configuration, tableName);
PhoenixConfigurationUtil.setSelectColumnNames(configuration, "A_BINARY");
final String selectStatement = PhoenixConfigurationUtil.getSelectStatement(configuration);
- final String expectedSelectStatement = "SELECT \"A_BINARY\" FROM " + SchemaUtil.getEscapedArgument(tableName) ;
+ final String expectedSelectStatement = "SELECT \"A_BINARY\" FROM " + tableName ;
assertEquals(expectedSelectStatement, selectStatement);
} finally {
conn.close();
@@ -115,7 +137,7 @@ public class PhoenixConfigurationUtilTest extends BaseConnectionlessQueryTest {
PhoenixConfigurationUtil.setSchemaType(configuration, SchemaType.QUERY);
PhoenixConfigurationUtil.setInputTableName(configuration, tableName);
final String selectStatement = PhoenixConfigurationUtil.getSelectStatement(configuration);
- final String expectedSelectStatement = "SELECT \"ID\",\"0\".\"VCARRAY\" FROM " + SchemaUtil.getEscapedArgument(tableName) ;
+ final String expectedSelectStatement = "SELECT \"ID\",\"0\".\"VCARRAY\" FROM " + tableName ;
assertEquals(expectedSelectStatement, selectStatement);
} finally {
conn.close();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c398e182/phoenix-core/src/test/java/org/apache/phoenix/util/QueryUtilTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/QueryUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/QueryUtilTest.java
index 8446e9e..45f536d 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/QueryUtilTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/QueryUtilTest.java
@@ -17,6 +17,11 @@
*/
package org.apache.phoenix.util;
+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.Types;
import java.util.Properties;
@@ -26,8 +31,6 @@ import org.junit.Test;
import com.google.common.collect.ImmutableList;
-import static org.junit.Assert.*;
-
public class QueryUtilTest {
private static final ColumnInfo ID_COLUMN = new ColumnInfo("ID", Types.BIGINT);
@@ -61,10 +64,37 @@ public class QueryUtilTest {
@Test
public void testConstructSelectStatement() {
assertEquals(
- "SELECT \"ID\",\"NAME\" FROM \"MYTAB\"",
+ "SELECT \"ID\",\"NAME\" FROM MYTAB",
QueryUtil.constructSelectStatement("MYTAB", ImmutableList.of(ID_COLUMN,NAME_COLUMN),null));
}
+ @Test
+ public void testConstructSelectStatementWithSchema() {
+ assertEquals(
+ "SELECT \"ID\",\"NAME\" FROM A.MYTAB",
+ QueryUtil.constructSelectStatement("A.MYTAB", ImmutableList.of(ID_COLUMN,NAME_COLUMN),null));
+ }
+
+ @Test
+ public void testConstructSelectStatementWithCaseSensitiveSchema() {
+ final String tableName = "MYTAB";
+ final String schemaName = SchemaUtil.getEscapedArgument("a");
+ final String fullTableName = SchemaUtil.getTableName(schemaName, tableName);
+ assertEquals(
+ "SELECT \"ID\",\"NAME\" FROM \"a\".MYTAB",
+ QueryUtil.constructSelectStatement(fullTableName, ImmutableList.of(ID_COLUMN,NAME_COLUMN),null));
+ }
+
+ @Test
+ public void testConstructSelectStatementWithCaseSensitiveTable() {
+ final String tableName = SchemaUtil.getEscapedArgument("mytab");
+ final String schemaName = SchemaUtil.getEscapedArgument("a");
+ final String fullTableName = SchemaUtil.getTableName(schemaName, tableName);
+ assertEquals(
+ "SELECT \"ID\",\"NAME\" FROM \"a\".\"mytab\"",
+ QueryUtil.constructSelectStatement(fullTableName, ImmutableList.of(ID_COLUMN,NAME_COLUMN),null));
+ }
+
/**
* Test that we create connection strings from the HBase Configuration that match the
* expected syntax. Expected to log exceptions as it uses ZK host names that don't exist
[18/50] [abbrv] phoenix git commit: PHOENIX-1954 Reserve chunks of
numbers for a sequence (Jan Fernando)
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/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 69520b0..a9f455a 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
@@ -135,6 +135,7 @@ import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.ReadOnlyTableException;
import org.apache.phoenix.schema.SaltingUtil;
import org.apache.phoenix.schema.Sequence;
+import org.apache.phoenix.schema.SequenceAllocation;
import org.apache.phoenix.schema.SequenceKey;
import org.apache.phoenix.schema.TableAlreadyExistsException;
import org.apache.phoenix.schema.TableNotFoundException;
@@ -2272,8 +2273,8 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
* Verifies that sequences exist and reserves values for them if reserveValues is true
*/
@Override
- public void validateSequences(List<SequenceKey> sequenceKeys, long timestamp, long[] values, SQLException[] exceptions, Sequence.ValueOp action) throws SQLException {
- incrementSequenceValues(sequenceKeys, timestamp, values, exceptions, action);
+ public void validateSequences(List<SequenceAllocation> sequenceAllocations, long timestamp, long[] values, SQLException[] exceptions, Sequence.ValueOp action) throws SQLException {
+ incrementSequenceValues(sequenceAllocations, timestamp, values, exceptions, action);
}
/**
@@ -2286,14 +2287,15 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
*
*/
@Override
- public void incrementSequences(List<SequenceKey> sequenceKeys, long timestamp, long[] values, SQLException[] exceptions) throws SQLException {
- incrementSequenceValues(sequenceKeys, timestamp, values, exceptions, Sequence.ValueOp.INCREMENT_SEQUENCE);
+ public void incrementSequences(List<SequenceAllocation> sequenceAllocations, long timestamp, long[] values, SQLException[] exceptions) throws SQLException {
+ incrementSequenceValues(sequenceAllocations, timestamp, values, exceptions, Sequence.ValueOp.INCREMENT_SEQUENCE);
}
@SuppressWarnings("deprecation")
- private void incrementSequenceValues(List<SequenceKey> keys, long timestamp, long[] values, SQLException[] exceptions, Sequence.ValueOp op) throws SQLException {
- List<Sequence> sequences = Lists.newArrayListWithExpectedSize(keys.size());
- for (SequenceKey key : keys) {
+ private void incrementSequenceValues(List<SequenceAllocation> sequenceAllocations, long timestamp, long[] values, SQLException[] exceptions, Sequence.ValueOp op) throws SQLException {
+ List<Sequence> sequences = Lists.newArrayListWithExpectedSize(sequenceAllocations.size());
+ for (SequenceAllocation sequenceAllocation : sequenceAllocations) {
+ SequenceKey key = sequenceAllocation.getSequenceKey();
Sequence newSequences = new Sequence(key);
Sequence sequence = sequenceMap.putIfAbsent(key, newSequences);
if (sequence == null) {
@@ -2312,11 +2314,11 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
for (int i = 0; i < sequences.size(); i++) {
Sequence sequence = sequences.get(i);
try {
- values[i] = sequence.incrementValue(timestamp, op);
+ values[i] = sequence.incrementValue(timestamp, op, sequenceAllocations.get(i).getNumAllocations());
} catch (EmptySequenceCacheException e) {
indexes[toIncrementList.size()] = i;
toIncrementList.add(sequence);
- Increment inc = sequence.newIncrement(timestamp, op);
+ Increment inc = sequence.newIncrement(timestamp, op, sequenceAllocations.get(i).getNumAllocations());
incrementBatch.add(inc);
} catch (SQLException e) {
exceptions[i] = e;
@@ -2355,7 +2357,8 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
Sequence sequence = toIncrementList.get(i);
Result result = (Result)resultObjects[i];
try {
- values[indexes[i]] = sequence.incrementValue(result, op);
+ long numToAllocate = Bytes.toLong(incrementBatch.get(i).getAttribute(SequenceRegionObserver.NUM_TO_ALLOCATE));
+ values[indexes[i]] = sequence.incrementValue(result, op, numToAllocate);
} catch (SQLException e) {
exceptions[indexes[i]] = e;
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/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 4d582be..3fa0c1e 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
@@ -66,6 +66,7 @@ import org.apache.phoenix.schema.PTableImpl;
import org.apache.phoenix.schema.PTableKey;
import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.Sequence;
+import org.apache.phoenix.schema.SequenceAllocation;
import org.apache.phoenix.schema.SequenceAlreadyExistsException;
import org.apache.phoenix.schema.SequenceInfo;
import org.apache.phoenix.schema.SequenceKey;
@@ -385,13 +386,13 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple
}
@Override
- public void validateSequences(List<SequenceKey> sequenceKeys, long timestamp, long[] values,
- SQLException[] exceptions, Sequence.ValueOp action) throws SQLException {
+ public void validateSequences(List<SequenceAllocation> sequenceAllocations, long timestamp,
+ long[] values, SQLException[] exceptions, Sequence.ValueOp action) throws SQLException {
int i = 0;
- for (SequenceKey key : sequenceKeys) {
- SequenceInfo info = sequenceMap.get(key);
+ for (SequenceAllocation sequenceAllocation : sequenceAllocations) {
+ SequenceInfo info = sequenceMap.get(sequenceAllocation.getSequenceKey());
if (info == null) {
- exceptions[i] = new SequenceNotFoundException(key.getSchemaName(), key.getSequenceName());
+ exceptions[i] = new SequenceNotFoundException(sequenceAllocation.getSequenceKey().getSchemaName(), sequenceAllocation.getSequenceKey().getSequenceName());
} else {
values[i] = info.sequenceValue;
}
@@ -400,10 +401,11 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple
}
@Override
- public void incrementSequences(List<SequenceKey> sequenceKeys, long timestamp, long[] values,
- SQLException[] exceptions) throws SQLException {
+ public void incrementSequences(List<SequenceAllocation> sequenceAllocations, long timestamp,
+ long[] values, SQLException[] exceptions) throws SQLException {
int i = 0;
- for (SequenceKey key : sequenceKeys) {
+ for (SequenceAllocation sequenceAllocation : sequenceAllocations) {
+ SequenceKey key = sequenceAllocation.getSequenceKey();
SequenceInfo info = sequenceMap.get(key);
if (info == null) {
exceptions[i] = new SequenceNotFoundException(
@@ -429,7 +431,7 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple
i = 0;
for (SQLException e : exceptions) {
if (e != null) {
- sequenceMap.remove(sequenceKeys.get(i));
+ sequenceMap.remove(sequenceAllocations.get(i).getSequenceKey());
}
i++;
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java
index 2a98cd5..4153652 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java
@@ -42,6 +42,7 @@ import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.Sequence;
+import org.apache.phoenix.schema.SequenceAllocation;
import org.apache.phoenix.schema.SequenceKey;
import org.apache.phoenix.schema.stats.PTableStats;
@@ -183,15 +184,15 @@ public class DelegateConnectionQueryServices extends DelegateQueryServices imple
}
@Override
- public void validateSequences(List<SequenceKey> sequenceKeys, long timestamp, long[] values,
- SQLException[] exceptions, Sequence.ValueOp action) throws SQLException {
- getDelegate().validateSequences(sequenceKeys, timestamp, values, exceptions, action);
+ public void validateSequences(List<SequenceAllocation> sequenceAllocations, long timestamp,
+ long[] values, SQLException[] exceptions, Sequence.ValueOp action) throws SQLException {
+ getDelegate().validateSequences(sequenceAllocations, timestamp, values, exceptions, action);
}
@Override
- public void incrementSequences(List<SequenceKey> sequenceKeys, long timestamp, long[] values,
- SQLException[] exceptions) throws SQLException {
- getDelegate().incrementSequences(sequenceKeys, timestamp, values, exceptions);
+ public void incrementSequences(List<SequenceAllocation> sequenceAllocations, long timestamp,
+ long[] values, SQLException[] exceptions) throws SQLException {
+ getDelegate().incrementSequences(sequenceAllocations, timestamp, values, exceptions);
}
@Override
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/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 9e74d2a..9d0c1aa 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
@@ -1255,7 +1255,7 @@ public class MetaDataClient {
dataTable.getTimeStamp());
long[] seqValues = new long[1];
SQLException[] sqlExceptions = new SQLException[1];
- connection.getQueryServices().incrementSequences(Collections.singletonList(key),
+ connection.getQueryServices().incrementSequences(Collections.singletonList(new SequenceAllocation(key, 1)),
Math.max(timestamp, dataTable.getTimeStamp()), seqValues, sqlExceptions);
if (sqlExceptions[0] != null) {
throw sqlExceptions[0];
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java
index aeba58b..adca5e8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/Sequence.java
@@ -62,7 +62,7 @@ import com.google.common.math.LongMath;
public class Sequence {
public static final int SUCCESS = 0;
- public enum ValueOp {VALIDATE_SEQUENCE, RESERVE_SEQUENCE, INCREMENT_SEQUENCE};
+ public enum ValueOp {VALIDATE_SEQUENCE, INCREMENT_SEQUENCE};
public enum MetaOp {CREATE_SEQUENCE, DROP_SEQUENCE, RETURN_SEQUENCE};
// create empty Sequence key values used while created a sequence row
@@ -144,7 +144,7 @@ public class Sequence {
return value.isDeleted ? null : value;
}
- private long increment(SequenceValue value, ValueOp op) throws SQLException {
+ private long increment(SequenceValue value, ValueOp op, long numToAllocate) throws SQLException {
boolean increasingSeq = value.incrementBy > 0 && op != ValueOp.VALIDATE_SEQUENCE;
// check if the the sequence has already reached the min/max limit
if (value.limitReached && op != ValueOp.VALIDATE_SEQUENCE) {
@@ -165,7 +165,8 @@ public class Sequence {
boolean overflowOrUnderflow=false;
// advance currentValue while checking for overflow
try {
- value.currentValue = LongMath.checkedAdd(value.currentValue, value.incrementBy);
+ // advance by numToAllocate * the increment amount
+ value.currentValue = LongMath.checkedAdd(value.currentValue, numToAllocate * value.incrementBy);
} catch (ArithmeticException e) {
overflowOrUnderflow = true;
}
@@ -180,18 +181,92 @@ public class Sequence {
return returnValue;
}
- public long incrementValue(long timestamp, ValueOp op) throws SQLException {
+ public long incrementValue(long timestamp, ValueOp op, long numToAllocate) throws SQLException {
SequenceValue value = findSequenceValue(timestamp);
if (value == null) {
throw EMPTY_SEQUENCE_CACHE_EXCEPTION;
}
- if (value.currentValue == value.nextValue) {
+
+ if (isSequenceCacheExhausted(numToAllocate, value)) {
if (op == ValueOp.VALIDATE_SEQUENCE) {
return value.currentValue;
}
throw EMPTY_SEQUENCE_CACHE_EXCEPTION;
- }
- return increment(value, op);
+ }
+ return increment(value, op, numToAllocate);
+ }
+
+ /**
+ * This method first checks whether value.currentValue = value.nextValue, this check is what
+ * determines whether we need to refresh the cache when evaluating NEXT VALUE FOR. Once
+ * current value reaches the next value we know the cache is exhausted as we give sequence
+ * values out one at time.
+ *
+ * However for bulk allocations, evaluated by NEXT <n> VALUE FOR, we need a different check
+ * @see isSequenceCacheExhaustedForBulkAllocation
+ *
+ * Using the bulk allocation method for determining if the cache is exhausted for both cases
+ * works in most of the cases, however when dealing with CYCLEs and overflow and underflow, things
+ * break down due to things like sign changes that can happen if we overflow from a positive to
+ * a negative number and vice versa. Therefore, leaving both checks in place.
+ *
+ */
+ private boolean isSequenceCacheExhausted(final long numToAllocate, final SequenceValue value) throws SQLException {
+ return value.currentValue == value.nextValue || (SequenceUtil.isBulkAllocation(numToAllocate) && isSequenceCacheExhaustedForBulkAllocation(numToAllocate, value));
+ }
+
+ /**
+ * This method checks whether there are sufficient values in the SequenceValue
+ * cached on the client to allocate the requested number of slots. It handles
+ * decreasing and increasing sequences as well as any overflows or underflows
+ * encountered.
+ */
+ private boolean isSequenceCacheExhaustedForBulkAllocation(final long numToAllocate, final SequenceValue value) throws SQLException {
+ long targetSequenceValue;
+
+ performValidationForBulkAllocation(numToAllocate, value);
+
+ try {
+ targetSequenceValue = LongMath.checkedAdd(value.currentValue, numToAllocate * value.incrementBy);
+ } catch (ArithmeticException e) {
+ // Perform a CheckedAdd to make sure if over/underflow
+ // We don't treat this as the cache being exhausted as the current value may be valid in the case
+ // of no cycle, logic in increment() will take care of detecting we've hit the limit of the sequence
+ return false;
+ }
+
+ if (value.incrementBy > 0) {
+ return targetSequenceValue > value.nextValue;
+ } else {
+ return targetSequenceValue < value.nextValue;
+ }
+ }
+
+ /**
+ * @throws SQLException with the correct error code if sequence limit is reached with
+ * this request for allocation or we attempt to perform a bulk allocation on a sequence
+ * with cycles.
+ */
+ private void performValidationForBulkAllocation(final long numToAllocate, final SequenceValue value)
+ throws SQLException {
+ boolean increasingSeq = value.incrementBy > 0 ? true : false;
+
+ // We don't support Bulk Allocations on sequences that have the CYCLE flag set to true
+ // Check for this here so we fail on expression evaluation and don't allow corner case
+ // whereby a client requests less than cached number of slots on sequence with cycle to succeed
+ if (value.cycle && !SequenceUtil.isCycleAllowed(numToAllocate)) {
+ throw new SQLExceptionInfo.Builder(SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_NOT_SUPPORTED)
+ .setSchemaName(key.getSchemaName())
+ .setTableName(key.getSequenceName())
+ .build().buildException();
+ }
+
+ if (SequenceUtil.checkIfLimitReached(value.currentValue, value.minValue, value.maxValue, value.incrementBy, value.cacheSize, numToAllocate)) {
+ throw new SQLExceptionInfo.Builder(SequenceUtil.getLimitReachedErrorCode(increasingSeq))
+ .setSchemaName(key.getSchemaName())
+ .setTableName(key.getSequenceName())
+ .build().buildException();
+ }
}
public List<Append> newReturns() {
@@ -249,7 +324,7 @@ public class Sequence {
return key;
}
- public long incrementValue(Result result, ValueOp op) throws SQLException {
+ public long incrementValue(Result result, ValueOp op, long numToAllocate) throws SQLException {
// In this case, we don't definitely know the timestamp of the deleted sequence,
// but we know anything older is likely deleted. Worse case, we remove a sequence
// from the cache that we shouldn't have which will cause a gap in sequence values.
@@ -270,19 +345,21 @@ public class Sequence {
.build().buildException();
}
// If we found the sequence, we update our cache with the new value
- SequenceValue value = new SequenceValue(result, op);
+ SequenceValue value = new SequenceValue(result, op, numToAllocate);
insertSequenceValue(value);
- return increment(value, op);
+ return increment(value, op, numToAllocate);
}
+
@SuppressWarnings("deprecation")
- public Increment newIncrement(long timestamp, Sequence.ValueOp action) {
+ public Increment newIncrement(long timestamp, Sequence.ValueOp action, long numToAllocate) {
Increment inc = new Increment(key.getKey());
// It doesn't matter what we set the amount too - we always use the values we get
// from the Get we do to prevent any race conditions. All columns that get added
// are returned with their current value
try {
inc.setTimeRange(MetaDataProtocol.MIN_TABLE_TIMESTAMP, timestamp);
+ inc.setAttribute(SequenceRegionObserver.NUM_TO_ALLOCATE, Bytes.toBytes(numToAllocate));
} catch (IOException e) {
throw new RuntimeException(e); // Impossible
}
@@ -413,7 +490,7 @@ public class Sequence {
return this.incrementBy == 0;
}
- public SequenceValue(Result r, ValueOp op) {
+ public SequenceValue(Result r, ValueOp op, long numToAllocate) {
KeyValue currentValueKV = getCurrentValueKV(r);
KeyValue incrementByKV = getIncrementByKV(r);
KeyValue cacheSizeKV = getCacheSizeKV(r);
@@ -429,8 +506,12 @@ public class Sequence {
this.cycle = (Boolean) PBoolean.INSTANCE.toObject(cycleKV.getValueArray(), cycleKV.getValueOffset(), cycleKV.getValueLength());
this.limitReached = false;
currentValue = nextValue;
+
if (op != ValueOp.VALIDATE_SEQUENCE) {
- currentValue -= incrementBy * cacheSize;
+ // We can't just take the max of numToAllocate and cacheSize
+ // We need to handle a valid edgecase where a client requests bulk allocation of
+ // a number of slots that are less than cache size of the sequence
+ currentValue -= incrementBy * (SequenceUtil.isBulkAllocation(numToAllocate) ? numToAllocate : cacheSize);
}
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java
new file mode 100644
index 0000000..afb4a20
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/SequenceAllocation.java
@@ -0,0 +1,48 @@
+package org.apache.phoenix.schema;
+
+/**
+ * A SequenceKey and the number of slots requested to be allocated for the sequence.
+ * It binds these two together to allow operations such as sorting
+ * a Collection of SequenceKeys and at the same time preserving the associated requested
+ * number of slots to allocate.
+ *
+ * This class delegates hashCode, equals and compareTo to @see{SequenceKey}.
+ *
+ */
+public class SequenceAllocation implements Comparable<SequenceAllocation> {
+
+ private final SequenceKey sequenceKey;
+ private final long numAllocations;
+
+ public SequenceAllocation(SequenceKey sequenceKey, long numAllocations) {
+ this.sequenceKey = sequenceKey;
+ this.numAllocations = numAllocations;
+ }
+
+
+ public SequenceKey getSequenceKey() {
+ return sequenceKey;
+ }
+
+
+ public long getNumAllocations() {
+ return numAllocations;
+ }
+
+
+ @Override
+ public int hashCode() {
+ return sequenceKey.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return sequenceKey.equals(obj);
+ }
+
+ @Override
+ public int compareTo(SequenceAllocation that) {
+ return sequenceKey.compareTo(that.sequenceKey);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/util/SequenceUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SequenceUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SequenceUtil.java
index f97d565..acf1864 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/SequenceUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SequenceUtil.java
@@ -16,6 +16,7 @@ import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.exception.SQLExceptionInfo;
import org.apache.phoenix.schema.SequenceInfo;
+import com.google.common.base.Preconditions;
import com.google.common.math.LongMath;
/**
@@ -23,17 +24,24 @@ import com.google.common.math.LongMath;
*/
public class SequenceUtil {
+ public static final long DEFAULT_NUM_SLOTS_TO_ALLOCATE = 1L;
+
/**
- * Returns the nextValue of a sequence
- * @throws SQLException if cycle is false and the sequence limit has been reached
+ * @return true if we limit of a sequence has been reached.
*/
public static boolean checkIfLimitReached(long currentValue, long minValue, long maxValue,
- long incrementBy, long cacheSize) throws SQLException {
+ long incrementBy, long cacheSize, long numToAllocate) {
long nextValue = 0;
boolean increasingSeq = incrementBy > 0 ? true : false;
// advance currentValue while checking for overflow
try {
- long incrementValue = LongMath.checkedMultiply(incrementBy, cacheSize);
+ long incrementValue;
+ if (isBulkAllocation(numToAllocate)) {
+ // For bulk allocation we increment independent of cache size
+ incrementValue = LongMath.checkedMultiply(incrementBy, numToAllocate);
+ } else {
+ incrementValue = LongMath.checkedMultiply(incrementBy, cacheSize);
+ }
nextValue = LongMath.checkedAdd(currentValue, incrementValue);
} catch (ArithmeticException e) {
return true;
@@ -46,9 +54,28 @@ public class SequenceUtil {
}
return false;
}
+
+ public static boolean checkIfLimitReached(long currentValue, long minValue, long maxValue,
+ long incrementBy, long cacheSize) throws SQLException {
+ return checkIfLimitReached(currentValue, minValue, maxValue, incrementBy, cacheSize, DEFAULT_NUM_SLOTS_TO_ALLOCATE);
+ }
public static boolean checkIfLimitReached(SequenceInfo info) throws SQLException {
- return checkIfLimitReached(info.sequenceValue, info.minValue, info.maxValue, info.incrementBy, info.cacheSize);
+ return checkIfLimitReached(info.sequenceValue, info.minValue, info.maxValue, info.incrementBy, info.cacheSize, DEFAULT_NUM_SLOTS_TO_ALLOCATE);
+ }
+
+ /**
+ * Returns true if the value of numToAllocate signals that a bulk allocation of sequence slots
+ * was requested. Prevents proliferation of same comparison in many places throughout the code.
+ */
+ public static boolean isBulkAllocation(long numToAllocate) {
+ Preconditions.checkArgument(numToAllocate > 0);
+ return numToAllocate > DEFAULT_NUM_SLOTS_TO_ALLOCATE;
+ }
+
+ public static boolean isCycleAllowed(long numToAllocate) {
+ return !isBulkAllocation(numToAllocate);
+
}
/**
@@ -59,5 +86,15 @@ public class SequenceUtil {
return new SQLExceptionInfo.Builder(code).setSchemaName(schemaName).setTableName(tableName)
.build().buildException();
}
+
+ /**
+ * Returns the correct instance of SQLExceptionCode when we detect a limit has been reached,
+ * depending upon whether a min or max value caused the limit to be exceeded.
+ */
+ public static SQLExceptionCode getLimitReachedErrorCode(boolean increasingSeq) {
+ SQLExceptionCode code = increasingSeq ? SQLExceptionCode.SEQUENCE_VAL_REACHED_MAX_VALUE
+ : SQLExceptionCode.SEQUENCE_VAL_REACHED_MIN_VALUE;
+ return code;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java
new file mode 100644
index 0000000..4a825f2
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/SequenceAllocationTest.java
@@ -0,0 +1,59 @@
+package org.apache.phoenix.schema;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.phoenix.query.QueryServicesOptions;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class SequenceAllocationTest {
+
+ @Test
+ /**
+ * Validates that sorting a List of SequenceAllocation instances
+ * results in the same sort order as sorting SequenceKey instances.
+ */
+ public void testSortingSequenceAllocation() {
+
+ // Arrange
+ SequenceKey sequenceKey1 = new SequenceKey(null, "seqalloc", "sequenceC",QueryServicesOptions.DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS);
+ SequenceKey sequenceKey2 = new SequenceKey(null, "seqalloc", "sequenceB",QueryServicesOptions.DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS);
+ SequenceKey sequenceKey3 = new SequenceKey(null, "seqalloc", "sequenceA",QueryServicesOptions.DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS);
+ List<SequenceKey> sequenceKeys = Lists.newArrayList(sequenceKey1, sequenceKey2, sequenceKey3);
+ List<SequenceAllocation> sequenceAllocations = Lists.newArrayList(new SequenceAllocation(sequenceKey2, 1), new SequenceAllocation(sequenceKey1, 1), new SequenceAllocation(sequenceKey3, 1));
+
+ // Act
+ Collections.sort(sequenceKeys);
+ Collections.sort(sequenceAllocations);
+
+ // Assert
+ int i = 0;
+ for (SequenceKey sequenceKey : sequenceKeys) {
+ assertEquals(sequenceKey, sequenceAllocations.get(i).getSequenceKey());
+ i++;
+ }
+ }
+
+ @Test
+ public void testSortingSequenceAllocationPreservesAllocations() {
+
+ // Arrange
+ SequenceKey sequenceKeyC = new SequenceKey(null, "seqalloc", "sequenceC",QueryServicesOptions.DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS);
+ SequenceKey sequenceKeyB = new SequenceKey(null, "seqalloc", "sequenceB",QueryServicesOptions.DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS);
+ SequenceKey sequenceKeyA = new SequenceKey(null, "seqalloc", "sequenceA",QueryServicesOptions.DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS);
+ List<SequenceAllocation> sequenceAllocations = Lists.newArrayList(new SequenceAllocation(sequenceKeyB, 15), new SequenceAllocation(sequenceKeyC, 11), new SequenceAllocation(sequenceKeyA, 1000));
+
+ // Act
+ Collections.sort(sequenceAllocations);
+
+ // Assert
+ assertEquals("sequenceA",sequenceAllocations.get(0).getSequenceKey().getSequenceName());
+ assertEquals(1000,sequenceAllocations.get(0).getNumAllocations());
+ assertEquals(15,sequenceAllocations.get(1).getNumAllocations());
+ assertEquals(11,sequenceAllocations.get(2).getNumAllocations());
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/test/java/org/apache/phoenix/util/SequenceUtilTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/SequenceUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/SequenceUtilTest.java
index f25a213..2abc482 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/SequenceUtilTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/SequenceUtilTest.java
@@ -62,4 +62,58 @@ public class SequenceUtilTest {
public void testDescendingOverflowCycle() throws SQLException {
assertTrue(SequenceUtil.checkIfLimitReached(Long.MIN_VALUE, Long.MIN_VALUE, 0, -1/* incrementBy */, CACHE_SIZE));
}
+
+ @Test
+ public void testBulkAllocationAscendingNextValueGreaterThanMax() throws SQLException {
+ assertTrue(SequenceUtil.checkIfLimitReached(MAX_VALUE, MIN_VALUE, MAX_VALUE, 2/* incrementBy */, CACHE_SIZE, 1));
+ }
+
+ @Test
+ public void testBulkAllocationAscendingNextValueReachLimit() throws SQLException {
+ assertFalse(SequenceUtil.checkIfLimitReached(6, MIN_VALUE, MAX_VALUE, 2/* incrementBy */, CACHE_SIZE, 2));
+ }
+
+ @Test
+ public void testBulkAllocationAscendingNextValueWithinLimit() throws SQLException {
+ assertFalse(SequenceUtil.checkIfLimitReached(5, MIN_VALUE, MAX_VALUE, 2/* incrementBy */, CACHE_SIZE, 2));
+
+ }
+
+ @Test
+ public void testBulkAllocationAscendingOverflow() throws SQLException {
+ assertTrue(SequenceUtil.checkIfLimitReached(Long.MAX_VALUE, 0, Long.MAX_VALUE, 1/* incrementBy */, CACHE_SIZE, 100));
+ }
+
+
+ @Test
+ public void testBulkAllocationDescendingNextValueLessThanMax() throws SQLException {
+ assertTrue(SequenceUtil.checkIfLimitReached(10, MIN_VALUE, MAX_VALUE, -2/* incrementBy */, CACHE_SIZE, 5));
+ }
+
+ @Test
+ public void testBulkAllocationDescendingNextValueReachLimit() throws SQLException {
+ assertFalse(SequenceUtil.checkIfLimitReached(7, MIN_VALUE, MAX_VALUE, -2/* incrementBy */, CACHE_SIZE, 3));
+ }
+
+ @Test
+ public void testBulkAllocationDescendingNextValueWithinLimit() throws SQLException {
+ assertFalse(SequenceUtil.checkIfLimitReached(8, MIN_VALUE, MAX_VALUE, -2/* incrementBy */, CACHE_SIZE, 2));
+
+ }
+
+ @Test
+ public void testBulkAllocationDescendingOverflowCycle() throws SQLException {
+ assertTrue(SequenceUtil.checkIfLimitReached(Long.MIN_VALUE, Long.MIN_VALUE, 0, -1/* incrementBy */, CACHE_SIZE, 100));
+ }
+
+ @Test
+ public void testIsCycleAllowedForBulkAllocation() {
+ assertFalse(SequenceUtil.isCycleAllowed(2));
+ }
+
+ @Test
+ public void testIsCycleAllowedForStandardAllocation() {
+ assertTrue(SequenceUtil.isCycleAllowed(1));
+ }
+
}
[10/50] [abbrv] phoenix git commit: PHOENIX-2095 Lower the default
for phoenix.sequence.saltBuckets
Posted by ma...@apache.org.
PHOENIX-2095 Lower the default for phoenix.sequence.saltBuckets
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/efb941ae
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/efb941ae
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/efb941ae
Branch: refs/heads/calcite
Commit: efb941aef6062fe704460fd37f9cc062c2ed2eee
Parents: 973bccb
Author: Andrew Purtell <ap...@apache.org>
Authored: Wed Jul 8 09:34:20 2015 -0700
Committer: Andrew Purtell <ap...@apache.org>
Committed: Wed Jul 8 09:34:20 2015 -0700
----------------------------------------------------------------------
.../main/java/org/apache/phoenix/query/QueryServicesOptions.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/efb941ae/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
index 3efd79f..ea81cf5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
@@ -174,7 +174,7 @@ public class QueryServicesOptions {
/**
* Use only first time SYSTEM.SEQUENCE table is created.
*/
- public static final int DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS = SaltingUtil.MAX_BUCKET_NUM;
+ public static final int DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS = 0;
/**
* Default value for coprocessor priority is between SYSTEM and USER priority.
*/
[05/50] [abbrv] phoenix git commit: Merge branch 'master' of
https://git-wip-us.apache.org/repos/asf/phoenix
Posted by ma...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/phoenix
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/1e606d57
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/1e606d57
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/1e606d57
Branch: refs/heads/calcite
Commit: 1e606d579965b97254f2c30399ace004a8912a31
Parents: ade12a7 c398e18
Author: maryannxue <we...@intel.com>
Authored: Sat Jul 4 14:05:00 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Sat Jul 4 14:05:00 2015 -0400
----------------------------------------------------------------------
.../util/PhoenixConfigurationUtilTest.java | 28 +++++++++++++--
.../org/apache/phoenix/util/QueryUtilTest.java | 36 ++++++++++++++++++--
2 files changed, 58 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
[11/50] [abbrv] phoenix git commit: PHOENIX-2097 Add new MD5 test for
composite PK
Posted by ma...@apache.org.
PHOENIX-2097 Add new MD5 test for composite PK
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/69e55df8
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/69e55df8
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/69e55df8
Branch: refs/heads/calcite
Commit: 69e55df8ff42aedf8c12da569dc5e85cc13eb95d
Parents: efb941a
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Jul 2 10:03:55 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Wed Jul 8 11:57:40 2015 -0700
----------------------------------------------------------------------
.../apache/phoenix/end2end/MD5FunctionIT.java | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/69e55df8/phoenix-core/src/it/java/org/apache/phoenix/end2end/MD5FunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MD5FunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MD5FunctionIT.java
index ff7ebdb..a6107df 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MD5FunctionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MD5FunctionIT.java
@@ -52,6 +52,25 @@ public class MD5FunctionIT extends BaseHBaseManagedTimeIT {
}
@Test
+ public void testRetrieveCompositeKey() throws Exception {
+ String testString = "FOOBAR";
+
+ Connection conn = DriverManager.getConnection(getUrl());
+ String ddl = "CREATE TABLE IF NOT EXISTS MD5_RETRIEVE_TEST (k1 CHAR(3) NOT NULL, k2 CHAR(3) NOT NULL, CONSTRAINT PK PRIMARY KEY (K1,K2))";
+ conn.createStatement().execute(ddl);
+ String dml = "UPSERT INTO MD5_RETRIEVE_TEST VALUES('FOO','BAR')";
+ conn.createStatement().execute(dml);
+ conn.commit();
+
+ ResultSet rs = conn.createStatement().executeQuery("SELECT MD5((K1,K2)) FROM MD5_RETRIEVE_TEST");
+ assertTrue(rs.next());
+ byte[] first = MessageDigest.getInstance("MD5").digest(testString.getBytes());
+ byte[] second = rs.getBytes(1);
+ assertArrayEquals(first, second);
+ assertFalse(rs.next());
+ }
+
+ @Test
public void testUpsert() throws Exception {
String testString1 = "mwalsh1";
String testString2 = "mwalsh2";
[43/50] [abbrv] phoenix git commit: PHOENIX-2123 Diverged view
prevents schema propagation to the entire view hierarchy
Posted by ma...@apache.org.
PHOENIX-2123 Diverged view prevents schema propagation to the entire view hierarchy
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/ec93ec79
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/ec93ec79
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/ec93ec79
Branch: refs/heads/calcite
Commit: ec93ec79c24cc847ed4a2777794da3cc0b0e3da3
Parents: 553d3cc
Author: Samarth <sa...@salesforce.com>
Authored: Wed Jul 15 13:34:39 2015 -0700
Committer: Samarth <sa...@salesforce.com>
Committed: Wed Jul 15 13:34:39 2015 -0700
----------------------------------------------------------------------
.../apache/phoenix/end2end/AlterTableIT.java | 34 +++++++++++---------
.../coprocessor/MetaDataEndpointImpl.java | 7 ++--
.../org/apache/phoenix/util/UpgradeUtil.java | 6 ++--
3 files changed, 24 insertions(+), 23 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ec93ec79/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 607f52a..1758dd4 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
@@ -2575,36 +2575,38 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
@Test
- public void testDivorcedViewsStayDivorced() throws Exception {
- String baseTable = "testDivorcedViewsStayDivorced";
- String viewName = baseTable + "_view";
+ public void testDivergedViewsStayDiverged() throws Exception {
+ String baseTable = "testDivergedViewsStayDiverged";
+ String view1 = baseTable + "_view1";
+ String view2 = baseTable + "_view2";
try (Connection conn = DriverManager.getConnection(getUrl())) {
String tableDDL = "CREATE TABLE " + baseTable + " (PK1 VARCHAR NOT NULL PRIMARY KEY, V1 VARCHAR, V2 VARCHAR)";
conn.createStatement().execute(tableDDL);
- String viewDDL = "CREATE VIEW " + viewName + " AS SELECT * FROM " + baseTable;
+ String viewDDL = "CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable;
+ conn.createStatement().execute(viewDDL);
+
+ viewDDL = "CREATE VIEW " + view2 + " AS SELECT * FROM " + baseTable;
conn.createStatement().execute(viewDDL);
- // Drop the column inherited from base table to divorce the view
- String dropColumn = "ALTER VIEW " + viewName + " DROP COLUMN V2";
+ // Drop the column inherited from base table to make it diverged
+ String dropColumn = "ALTER VIEW " + view1 + " DROP COLUMN V2";
conn.createStatement().execute(dropColumn);
String alterBaseTable = "ALTER TABLE " + baseTable + " ADD V3 VARCHAR";
- try {
- conn.createStatement().execute(alterBaseTable);
- fail();
- }
- catch (SQLException e) {
- assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
- }
-
- // Column V3 shouldn't have propagated to the divorced view.
- String sql = "SELECT V3 FROM " + viewName;
+ conn.createStatement().execute(alterBaseTable);
+
+ // Column V3 shouldn't have propagated to the diverged view.
+ String sql = "SELECT V3 FROM " + view1;
try {
conn.createStatement().execute(sql);
} catch (SQLException e) {
assertEquals(SQLExceptionCode.COLUMN_NOT_FOUND.getErrorCode(), e.getErrorCode());
}
+
+ // However, column V3 should have propagated to the non-diverged view.
+ sql = "SELECT V3 FROM " + view2;
+ conn.createStatement().execute(sql);
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ec93ec79/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index 5396a69..05e7acb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -1693,11 +1693,10 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
RowLock viewRowLock = acquireLock(region, viewKey, locks);
PTable view = doGetTable(viewKey, clientTimeStamp, viewRowLock);
if (view.getBaseColumnCount() == QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT) {
- // if a view has divorced itself from the base table, we don't allow schema changes
+ // if a view has diverged from the base table, we don't allow schema changes
// to be propagated to it.
- // FIXME: we should allow the update, but just not propagate it to this view
- // The one exception is PK changes which need to be propagated to diverged views as well
- return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
+ // FIXME: We should allow PK changes to be propagated to a diverged view See PHOENIX-2110
+ continue;
}
int numColsAddedToBaseTable = 0;
int numColsAddedToView = 0;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ec93ec79/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
index e1e2515..b4fcef8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
@@ -637,9 +637,9 @@ public class UpgradeUtil {
* two till one of the following happens:
*
* 1) We run into a view column which is different from column in the base physical table.
- * This means that the view has divorced itself from the base physical table. In such a case
+ * This means that the view has diverged from the base physical table. In such a case
* we will set a special value for the base column count. That special value will also be used
- * on the server side to filter out the divorced view so that meta-data changes on the base
+ * on the server side to filter out the diverged view so that meta-data changes on the base
* physical table are not propagated to it.
*
* 2) Every physical table column is present in the view. In that case we set the base column count
@@ -667,7 +667,7 @@ public class UpgradeUtil {
clearCache = true;
}
} else {
- // special value to denote that the view has divorced itself from the base physical table.
+ // special value to denote that the view has diverged from the base physical table.
upsertBaseColumnCountInHeaderRow(metaConnection, viewTenantId, viewSchema, viewName, DIVERGED_VIEW_BASE_COLUMN_COUNT);
baseColumnCountUpserted = true;
clearCache = true;
[44/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns - ARRAY addendum (Dumindu Buddhika)
Posted by ma...@apache.org.
PHOENIX-2067 Sort order incorrect for variable length DESC columns - ARRAY
addendum (Dumindu Buddhika)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/33d60506
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/33d60506
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/33d60506
Branch: refs/heads/calcite
Commit: 33d60506c5f2d4408a1df79f278d7a45d3401a27
Parents: ec93ec7
Author: ramkrishna <ra...@gmail.com>
Authored: Thu Jul 16 21:13:31 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Thu Jul 16 21:13:31 2015 +0530
----------------------------------------------------------------------
.../phoenix/schema/types/PArrayDataType.java | 14 +-
.../expression/ArrayAppendFunctionTest.java | 76 ++++++++---
.../expression/ArrayConcatFunctionTest.java | 129 +++++++++++++++++++
.../expression/ArrayPrependFunctionTest.java | 61 +++++++++
.../schema/types/PDataTypeForArraysTest.java | 70 +++++++++-
5 files changed, 324 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
index dd11569..9ca64c5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
@@ -379,10 +379,10 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
int currOffset = getOffset(bytes, arrayIndex, useShort, indexOffset);
int elementLength = 0;
if (arrayIndex == (noOfElements - 1)) {
- elementLength = bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE ? 0 : indexOffset
+ elementLength = (bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + initPos] == QueryConstants.DESC_SEPARATOR_BYTE) ? 0 : indexOffset
- (currOffset + initPos) - 3;
} else {
- elementLength = bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE ? 0 : getOffset(bytes,
+ elementLength = (bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + initPos] == QueryConstants.DESC_SEPARATOR_BYTE) ? 0 : getOffset(bytes,
arrayIndex + 1, useShort, indexOffset) - currOffset - 1;
}
ptr.set(bytes, currOffset + initPos, elementLength);
@@ -426,10 +426,10 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
int currOffset = getOffset(bytes, arrayIndex, useShort, indexOffset);
int elementLength = 0;
if (arrayIndex == (noOfElements - 1)) {
- elementLength = bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE ? 0 : indexOffset
+ elementLength = (bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + offset] == QueryConstants.DESC_SEPARATOR_BYTE) ? 0 : indexOffset
- (currOffset + offset) - 3;
} else {
- elementLength = bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE ? 0 : getOffset(bytes,
+ elementLength = (bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + offset] == QueryConstants.DESC_SEPARATOR_BYTE) ? 0 : getOffset(bytes,
arrayIndex + 1, useShort, indexOffset) - currOffset - 1;
}
ptr.set(bytes, currOffset + offset, elementLength);
@@ -831,7 +831,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
// count nulls at the end of array 1
for (int index = actualLengthOfArray1 - 1; index > -1; index--) {
int offset = getOffset(array1Bytes, index, !useIntArray1, array1BytesOffset + offsetArrayPositionArray1);
- if (array1Bytes[array1BytesOffset + offset] == QueryConstants.SEPARATOR_BYTE) {
+ if (array1Bytes[array1BytesOffset + offset] == QueryConstants.SEPARATOR_BYTE || array1Bytes[array1BytesOffset + offset] == QueryConstants.DESC_SEPARATOR_BYTE) {
nullsAtTheEndOfArray1++;
} else {
break;
@@ -1064,11 +1064,11 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
nextOff = getOffset(indexArr, countOfElementsRead + 1, useShort, indexOffset);
}
countOfElementsRead++;
- if ((bytes[currOffset + initPos] != QueryConstants.SEPARATOR_BYTE) && foundNull) {
+ if ((bytes[currOffset + initPos] != QueryConstants.SEPARATOR_BYTE && bytes[currOffset + initPos] != QueryConstants.DESC_SEPARATOR_BYTE) && foundNull) {
// Found a non null element
foundNull = false;
}
- if (bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE) {
+ if (bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + initPos] == QueryConstants.DESC_SEPARATOR_BYTE) {
// Null element
foundNull = true;
i++;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java
index 5405ef3..a98bccc 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java
@@ -17,6 +17,7 @@
*/
package org.apache.phoenix.expression;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
@@ -27,21 +28,7 @@ import java.util.List;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.expression.function.ArrayAppendFunction;
import org.apache.phoenix.schema.SortOrder;
-import org.apache.phoenix.schema.types.PBoolean;
-import org.apache.phoenix.schema.types.PChar;
-import org.apache.phoenix.schema.types.PDataType;
-import org.apache.phoenix.schema.types.PDate;
-import org.apache.phoenix.schema.types.PDecimal;
-import org.apache.phoenix.schema.types.PDouble;
-import org.apache.phoenix.schema.types.PFloat;
-import org.apache.phoenix.schema.types.PInteger;
-import org.apache.phoenix.schema.types.PLong;
-import org.apache.phoenix.schema.types.PSmallint;
-import org.apache.phoenix.schema.types.PTime;
-import org.apache.phoenix.schema.types.PTimestamp;
-import org.apache.phoenix.schema.types.PTinyint;
-import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.schema.types.PhoenixArray;
+import org.apache.phoenix.schema.types.*;
import org.junit.Test;
import com.google.common.collect.Lists;
@@ -357,4 +344,63 @@ public class ArrayAppendFunctionTest {
test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
}
+ @Test
+ public void testForCorrectSeparatorBytes1() throws Exception {
+ Object[] o = new Object[]{"a", "b", "c"};
+ Object element = "d";
+ PDataType baseType = PVarchar.INSTANCE;
+
+ PhoenixArray arr = new PhoenixArray(baseType, o);
+ LiteralExpression arrayLiteral, elementLiteral;
+ arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) arrayLiteral);
+ expressions.add(elementLiteral);
+
+ Expression arrayAppendFunction = new ArrayAppendFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayAppendFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{97, 0, 98, 0, 99, 0, 100, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 4, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes2() throws Exception {
+ Object[] o = new Object[]{"a", "b", "c"};
+ Object element = "d";
+ PDataType baseType = PVarchar.INSTANCE;
+
+ PhoenixArray arr = new PhoenixArray(baseType, o);
+ LiteralExpression arrayLiteral, elementLiteral;
+ arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) arrayLiteral);
+ expressions.add(elementLiteral);
+
+ Expression arrayAppendFunction = new ArrayAppendFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayAppendFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{-98, -1, -99, -1, -100, -1, -101, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 4, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes3() throws Exception {
+ Object[] o = new Object[]{"a", null, null, "c"};
+ Object element = "d";
+ PDataType baseType = PVarchar.INSTANCE;
+
+ PhoenixArray arr = new PhoenixArray(baseType, o);
+ LiteralExpression arrayLiteral, elementLiteral;
+ arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) arrayLiteral);
+ expressions.add(elementLiteral);
+
+ Expression arrayAppendFunction = new ArrayAppendFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayAppendFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{-98, -1, 0, -2, -100, -1, -101, -1, -1, -1, -128, 1, -128, 3, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 5, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java
index 75d0827..f23729e 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java
@@ -18,6 +18,7 @@
package org.apache.phoenix.expression;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.math.BigDecimal;
@@ -485,6 +486,9 @@ public class ArrayConcatFunctionTest {
PhoenixArray arr2 = new PhoenixArray(base, o2);
PhoenixArray expected = new PhoenixArray(base, e);
test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
}
@Test
@@ -504,6 +508,9 @@ public class ArrayConcatFunctionTest {
PhoenixArray arr2 = new PhoenixArray(base, o2);
PhoenixArray expected = new PhoenixArray(base, e);
test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
}
@Test
@@ -523,6 +530,9 @@ public class ArrayConcatFunctionTest {
PhoenixArray arr2 = new PhoenixArray(base, o2);
PhoenixArray expected = new PhoenixArray(base, e);
test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
}
@Test
@@ -542,6 +552,9 @@ public class ArrayConcatFunctionTest {
PhoenixArray arr2 = new PhoenixArray(base, o2);
PhoenixArray expected = new PhoenixArray(base, e);
test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
}
@Test
@@ -561,6 +574,9 @@ public class ArrayConcatFunctionTest {
PhoenixArray arr2 = new PhoenixArray(base, o2);
PhoenixArray expected = new PhoenixArray(base, e);
test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
}
@Test
@@ -580,5 +596,118 @@ public class ArrayConcatFunctionTest {
PhoenixArray arr2 = new PhoenixArray(base, o2);
PhoenixArray expected = new PhoenixArray(base, e);
test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+ test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes1() throws Exception {
+ Object[] o1 = new Object[]{"a", "b"};
+ Object[] o2 = new Object[]{"c", "d", "e"};
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+
+ PhoenixArray arr1 = new PhoenixArray(base, o1);
+ PhoenixArray arr2 = new PhoenixArray(base, o2);
+ LiteralExpression array1Literal, array2Literal;
+ array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+ expressions.add(array2Literal);
+
+ Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayConcatFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 7, -128, 9, 0, 0, 0, 12, 0, 0, 0, 5, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes2() throws Exception {
+ Object[] o1 = new Object[]{"a", "b"};
+ Object[] o2 = new Object[]{"c", "d", "e"};
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+
+ PhoenixArray arr1 = new PhoenixArray(base, o1);
+ PhoenixArray arr2 = new PhoenixArray(base, o2);
+ LiteralExpression array1Literal, array2Literal;
+ array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+ expressions.add(array2Literal);
+
+ Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayConcatFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 7, -128, 9, 0, 0, 0, 12, 0, 0, 0, 5, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes3() throws Exception {
+ Object[] o1 = new Object[]{"a", "b"};
+ Object[] o2 = new Object[]{"c", "d", "e"};
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+
+ PhoenixArray arr1 = new PhoenixArray(base, o1);
+ PhoenixArray arr2 = new PhoenixArray(base, o2);
+ LiteralExpression array1Literal, array2Literal;
+ array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+ expressions.add(array2Literal);
+
+ Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayConcatFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{-98, -1, -99, -1, -100, -1, -101, -1, -102, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 7, -128, 9, 0, 0, 0, 12, 0, 0, 0, 5, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes4() throws Exception {
+ Object[] o1 = new Object[]{"a", "b", null};
+ Object[] o2 = new Object[]{null, "c", "d", "e"};
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+
+ PhoenixArray arr1 = new PhoenixArray(base, o1);
+ PhoenixArray arr2 = new PhoenixArray(base, o2);
+ LiteralExpression array1Literal, array2Literal;
+ array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+ expressions.add(array2Literal);
+
+ Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayConcatFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{97, 0, 98, 0, 0, -2, 99, 0, 100, 0, 101, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 5, -128, 7, -128, 9, -128, 11, 0, 0, 0, 14, 0, 0, 0, 7, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes5() throws Exception {
+ Object[] o1 = new Object[]{"a", "b", null, null};
+ Object[] o2 = new Object[]{null, "c", "d", "e"};
+ PDataType type = PVarcharArray.INSTANCE;
+ PDataType base = PVarchar.INSTANCE;
+
+ PhoenixArray arr1 = new PhoenixArray(base, o1);
+ PhoenixArray arr2 = new PhoenixArray(base, o2);
+ LiteralExpression array1Literal, array2Literal;
+ array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+ expressions.add(array2Literal);
+
+ Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayConcatFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{-98, -1, -99, -1, 0, -3, -100, -1, -101, -1, -102, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 5, -128, 5, -128, 7, -128, 9, -128, 11, 0, 0, 0, 14, 0, 0, 0, 8, 1};
+ assertArrayEquals(expected, ptr.get());
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
index 4d2f960..b64f013 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
@@ -17,6 +17,7 @@
*/
package org.apache.phoenix.expression;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.math.BigDecimal;
@@ -549,4 +550,64 @@ public class ArrayPrependFunctionTest {
PhoenixArray expected = new PhoenixArray(baseType, o2);
test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
}
+
+ @Test
+ public void testForCorrectSeparatorBytes1() throws Exception {
+ Object[] o = new Object[]{"a", "b", "c"};
+ Object element = "d";
+ PDataType baseType = PVarchar.INSTANCE;
+
+ PhoenixArray arr = new PhoenixArray(baseType, o);
+ LiteralExpression arrayLiteral, elementLiteral;
+ arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) elementLiteral);
+ expressions.add(arrayLiteral);
+
+ Expression arrayPrependFunction = new ArrayPrependFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayPrependFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{100, 0, 97, 0, 98, 0, 99, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 4, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes2() throws Exception {
+ Object[] o = new Object[]{"a", "b", "c"};
+ Object element = "d";
+ PDataType baseType = PVarchar.INSTANCE;
+
+ PhoenixArray arr = new PhoenixArray(baseType, o);
+ LiteralExpression arrayLiteral, elementLiteral;
+ arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) elementLiteral);
+ expressions.add(arrayLiteral);
+
+ Expression arrayPrependFunction = new ArrayPrependFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayPrependFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{-101, -1, -98, -1, -99, -1, -100, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 4, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
+
+ @Test
+ public void testForCorrectSeparatorBytes3() throws Exception {
+ Object[] o = new Object[]{"a", null, null, "c"};
+ Object element = "d";
+ PDataType baseType = PVarchar.INSTANCE;
+
+ PhoenixArray arr = new PhoenixArray(baseType, o);
+ LiteralExpression arrayLiteral, elementLiteral;
+ arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.DESC, Determinism.ALWAYS);
+ elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+ List<Expression> expressions = Lists.newArrayList((Expression) elementLiteral);
+ expressions.add(arrayLiteral);
+
+ Expression arrayPrependFunction = new ArrayPrependFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ arrayPrependFunction.evaluate(null, ptr);
+ byte[] expected = new byte[]{-101, -1, -98, -1, 0, -2, -100, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 5, 1};
+ assertArrayEquals(expected, ptr.get());
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java
index 0610cda..7246020 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java
@@ -17,9 +17,6 @@
*/
package org.apache.phoenix.schema.types;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Time;
@@ -27,6 +24,8 @@ import java.sql.Timestamp;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.types.PArrayDataType;
import org.apache.phoenix.schema.types.PBoolean;
import org.apache.phoenix.schema.types.PBooleanArray;
@@ -76,6 +75,8 @@ import org.apache.phoenix.schema.types.PhoenixArray;
import org.junit.Ignore;
import org.junit.Test;
+import static org.junit.Assert.*;
+
public class PDataTypeForArraysTest {
@Test
public void testForIntegerArray() {
@@ -1137,5 +1138,66 @@ public class PDataTypeForArraysTest {
byte[] bytes2 = PVarcharArray.INSTANCE.toBytes(arr);
assertTrue(Bytes.compareTo(bytes1, bytes2) == 0);
}
-
+
+ @Test
+ public void testIsRowKeyOrderOptimized1() {
+ Object[] objects = new Object[]{"a", "b", "c"};
+ PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+ byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, PVarchar.INSTANCE, SortOrder.ASC);
+ assertTrue(PArrayDataType.isRowKeyOrderOptimized(PVarcharArray.INSTANCE, SortOrder.ASC, bytes, 0, bytes.length));
+ }
+
+ @Test
+ public void testIsRowKeyOrderOptimized2() {
+ Object[] objects = new Object[]{"a", "b", "c"};
+ PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+ byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, SortOrder.DESC);
+ assertTrue(PArrayDataType.isRowKeyOrderOptimized(PVarcharArray.INSTANCE, SortOrder.DESC, bytes, 0, bytes.length));
+ }
+
+ @Test
+ public void testIsRowKeyOrderOptimized3() {
+ Object[] objects = new Object[]{"a", "b", "c"};
+ PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+ byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, SortOrder.DESC);
+ for (int i = 0; i < bytes.length; i++) {
+ if (bytes[i] == QueryConstants.DESC_SEPARATOR_BYTE) {
+ bytes[i] = QueryConstants.SEPARATOR_BYTE;
+ }
+ }
+ assertFalse(PArrayDataType.isRowKeyOrderOptimized(PVarcharArray.INSTANCE, SortOrder.DESC, bytes, 0, bytes.length));
+ }
+
+ @Test
+ public void testIsRowKeyOrderOptimized4() {
+ assertTrue(PArrayDataType.isRowKeyOrderOptimized(PVarcharArray.INSTANCE, SortOrder.DESC, null, 0, 0));
+ }
+
+ @Test
+ public void testIsRowKeyOrderOptimized5() {
+ Object[] objects = new Object[]{1, 2, 3};
+ PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(PInteger.INSTANCE, objects);
+ byte[] bytes = PIntegerArray.INSTANCE.toBytes(arr, PInteger.INSTANCE, SortOrder.ASC);
+ assertTrue(PArrayDataType.isRowKeyOrderOptimized(PIntegerArray.INSTANCE, SortOrder.ASC, bytes, 0, bytes.length));
+ }
+
+ @Test
+ public void testVarcharArrayDesc(){
+ Object[] objects = new Object[]{"a", "b", null};
+ PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+ byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, PVarchar.INSTANCE, SortOrder.DESC);
+ PhoenixArray arr2 = (PhoenixArray)PVarcharArray.INSTANCE.toObject(bytes, SortOrder.DESC);
+ assertEquals(arr, arr2);
+ }
+
+ @Test
+ public void testPositionAtArrayElementWithDescArray(){
+ Object[] objects = new Object[]{"a", "b", null};
+ PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+ byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, PVarchar.INSTANCE, SortOrder.DESC);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable(bytes);
+ PArrayDataType.positionAtArrayElement(ptr, 2, PVarchar.INSTANCE, null);
+ String value = (String)PVarchar.INSTANCE.toObject(ptr, SortOrder.DESC);
+ assertEquals(null, value);
+ }
}
[31/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
index 60d2020..2c91dc5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java
@@ -47,1060 +47,1036 @@ import com.google.common.primitives.Longs;
*/
public abstract class PDataType<T> implements DataType<T>, Comparable<PDataType<?>> {
- private final String sqlTypeName;
- private final int sqlType;
- private final Class clazz;
- private final byte[] clazzNameBytes;
- private final byte[] sqlTypeNameBytes;
- private final PDataCodec codec;
- private final int ordinal;
-
- protected PDataType(String sqlTypeName, int sqlType, Class clazz, PDataCodec codec, int ordinal) {
- this.sqlTypeName = sqlTypeName;
- this.sqlType = sqlType;
- this.clazz = clazz;
- this.clazzNameBytes = Bytes.toBytes(clazz.getName());
- this.sqlTypeNameBytes = Bytes.toBytes(sqlTypeName);
- this.codec = codec;
- this.ordinal = ordinal;
- }
-
- @Deprecated
- public static PDataType[] values() {
- return PDataTypeFactory.getInstance().getOrderedTypes();
- }
-
- @Deprecated
- public int ordinal() {
- return ordinal;
- }
-
- @Override
- public Class<T> encodedClass() {
- return getJavaClass();
- }
-
- public boolean isCastableTo(PDataType targetType) {
- return isComparableTo(targetType);
- }
-
- public final PDataCodec getCodec() {
- return codec;
- }
-
- public boolean isBytesComparableWith(PDataType otherType) {
- return this == otherType
- || this.getClass() == PVarbinary.class
- || otherType == PVarbinary.INSTANCE
- || this.getClass() == PBinary.class
- || otherType == PBinary.INSTANCE;
- }
-
- public int estimateByteSize(Object o) {
- if (isFixedWidth()) {
- return getByteSize();
- }
- if (isArrayType()) {
- PhoenixArray array = (PhoenixArray) o;
- int noOfElements = array.numElements;
- int totalVarSize = 0;
- for (int i = 0; i < noOfElements; i++) {
- totalVarSize += array.estimateByteSize(i);
- }
- return totalVarSize;
- }
- // Non fixed width types must override this
- throw new UnsupportedOperationException();
- }
-
- public Integer getMaxLength(Object o) {
- return null;
- }
-
- public Integer getScale(Object o) {
- return null;
- }
-
- /**
- * Estimate the byte size from the type length. For example, for char, byte size would be the
- * same as length. For decimal, byte size would have no correlation with the length.
- */
- public Integer estimateByteSizeFromLength(Integer length) {
- if (isFixedWidth()) {
- return getByteSize();
- }
- if (isArrayType()) {
- return null;
- }
- // If not fixed width, default to say the byte size is the same as length.
- return length;
- }
-
- public final String getSqlTypeName() {
- return sqlTypeName;
- }
-
- public final int getSqlType() {
- return sqlType;
- }
-
- public final Class getJavaClass() {
- return clazz;
- }
-
- public boolean isArrayType() {
- return false;
- }
-
- public final int compareTo(byte[] lhs, int lhsOffset, int lhsLength, SortOrder lhsSortOrder,
- byte[] rhs, int rhsOffset, int rhsLength, SortOrder rhsSortOrder,
- PDataType rhsType) {
- Preconditions.checkNotNull(lhsSortOrder);
- Preconditions.checkNotNull(rhsSortOrder);
- if (this.isBytesComparableWith(rhsType)) { // directly compare the bytes
- return compareTo(lhs, lhsOffset, lhsLength, lhsSortOrder, rhs, rhsOffset, rhsLength,
- rhsSortOrder);
- }
- PDataCodec lhsCodec = this.getCodec();
- if (lhsCodec
- == null) { // no lhs native type representation, so convert rhsType to bytes representation of lhsType
- byte[] rhsConverted =
- this.toBytes(this.toObject(rhs, rhsOffset, rhsLength, rhsType, rhsSortOrder));
- if (rhsSortOrder == SortOrder.DESC) {
- rhsSortOrder = SortOrder.ASC;
- }
- if (lhsSortOrder == SortOrder.DESC) {
- lhs = SortOrder.invert(lhs, lhsOffset, new byte[lhsLength], 0, lhsLength);
- }
- return Bytes.compareTo(lhs, lhsOffset, lhsLength, rhsConverted, 0, rhsConverted.length);
- }
- PDataCodec rhsCodec = rhsType.getCodec();
- if (rhsCodec == null) {
- byte[] lhsConverted =
- rhsType.toBytes(rhsType.toObject(lhs, lhsOffset, lhsLength, this, lhsSortOrder));
- if (lhsSortOrder == SortOrder.DESC) {
- lhsSortOrder = SortOrder.ASC;
- }
- if (rhsSortOrder == SortOrder.DESC) {
- rhs = SortOrder.invert(rhs, rhsOffset, new byte[rhsLength], 0, rhsLength);
- }
- return Bytes.compareTo(lhsConverted, 0, lhsConverted.length, rhs, rhsOffset, rhsLength);
- }
- // convert to native and compare
- if (this.isCoercibleTo(PLong.INSTANCE)
- && rhsType
- .isCoercibleTo(PLong.INSTANCE)) { // native long to long comparison
- return Longs.compare(this.getCodec().decodeLong(lhs, lhsOffset, lhsSortOrder),
- rhsType.getCodec().decodeLong(rhs, rhsOffset, rhsSortOrder));
- } else if (isDoubleOrFloat(this) && isDoubleOrFloat(
- rhsType)) { // native double to double comparison
- return Doubles.compare(this.getCodec().decodeDouble(lhs, lhsOffset, lhsSortOrder),
- rhsType.getCodec().decodeDouble(rhs, rhsOffset, rhsSortOrder));
- } else { // native float/double to long comparison
- float fvalue = 0.0F;
- double dvalue = 0.0;
- long lvalue = 0;
- boolean isFloat = false;
- int invert = 1;
-
- if (this.isCoercibleTo(PLong.INSTANCE)) {
- lvalue = this.getCodec().decodeLong(lhs, lhsOffset, lhsSortOrder);
- } else if (this.getClass() == PFloat.class) {
- isFloat = true;
- fvalue = this.getCodec().decodeFloat(lhs, lhsOffset, lhsSortOrder);
- } else if (this.isCoercibleTo(PDouble.INSTANCE)) {
- dvalue = this.getCodec().decodeDouble(lhs, lhsOffset, lhsSortOrder);
- }
- if (rhsType.isCoercibleTo(PLong.INSTANCE)) {
- lvalue = rhsType.getCodec().decodeLong(rhs, rhsOffset, rhsSortOrder);
- } else if (rhsType == PFloat.INSTANCE) {
- invert = -1;
- isFloat = true;
- fvalue = rhsType.getCodec().decodeFloat(rhs, rhsOffset, rhsSortOrder);
- } else if (rhsType.isCoercibleTo(PDouble.INSTANCE)) {
- invert = -1;
- dvalue = rhsType.getCodec().decodeDouble(rhs, rhsOffset, rhsSortOrder);
- }
- // Invert the comparison if float/double value is on the RHS
- return invert * (isFloat ?
- compareFloatToLong(fvalue, lvalue) :
- compareDoubleToLong(dvalue, lvalue));
- }
- }
-
- public static boolean isDoubleOrFloat(PDataType type) {
- return type == PFloat.INSTANCE
- || type == PDouble.INSTANCE
- || type == PUnsignedFloat.INSTANCE || type == PUnsignedDouble.INSTANCE;
- }
-
- /**
- * Compares a float against a long. Behaves better than
- * {@link #compareDoubleToLong(double, long)} for float
- * values outside of Integer.MAX_VALUE and Integer.MIN_VALUE.
- *
- * @param f a float value
- * @param l a long value
- * @return -1 if f is less than l, 1 if f is greater than l, and 0 if f is equal to l
- */
- private static int compareFloatToLong(float f, long l) {
- if (f > Integer.MAX_VALUE || f < Integer.MIN_VALUE) {
- return f < l ? -1 : f > l ? 1 : 0;
- }
- long diff = (long) f - l;
- return Long.signum(diff);
- }
-
- /**
- * Compares a double against a long.
- *
- * @param d a double value
- * @param l a long value
- * @return -1 if d is less than l, 1 if d is greater than l, and 0 if d is equal to l
- */
- private static int compareDoubleToLong(double d, long l) {
- if (d > Long.MAX_VALUE) {
- return 1;
- }
- if (d < Long.MIN_VALUE) {
- return -1;
- }
- long diff = (long) d - l;
- return Long.signum(diff);
- }
-
- protected static void checkForSufficientLength(byte[] b, int offset, int requiredLength) {
- if (b.length < offset + requiredLength) {
- throw new RuntimeException(new SQLExceptionInfo.Builder(SQLExceptionCode.ILLEGAL_DATA)
- .setMessage(
- "Expected length of at least " + requiredLength + " bytes, but had " + (b.length
- - offset)).build().buildException());
- }
- }
-
- protected static Void throwConstraintViolationException(PDataType source, PDataType target) {
- throw new ConstraintViolationException(
- new SQLExceptionInfo.Builder(SQLExceptionCode.TYPE_MISMATCH)
- .setMessage(source + " cannot be coerced to " + target).build().buildException());
- }
-
- protected static RuntimeException newIllegalDataException() {
- return new IllegalDataException(new SQLExceptionInfo.Builder(SQLExceptionCode.ILLEGAL_DATA)
- .build().buildException());
- }
-
- protected static RuntimeException newIllegalDataException(String msg) {
- return new IllegalDataException(new SQLExceptionInfo.Builder(SQLExceptionCode.ILLEGAL_DATA)
- .setMessage(msg).build().buildException());
- }
-
- protected static RuntimeException newIllegalDataException(Exception e) {
- return new IllegalDataException(new SQLExceptionInfo.Builder(SQLExceptionCode.ILLEGAL_DATA)
- .setRootCause(e).build().buildException());
- }
+ private final String sqlTypeName;
+ private final int sqlType;
+ private final Class clazz;
+ private final byte[] clazzNameBytes;
+ private final byte[] sqlTypeNameBytes;
+ private final PDataCodec codec;
+ private final int ordinal;
+
+ protected PDataType(String sqlTypeName, int sqlType, Class clazz, PDataCodec codec, int ordinal) {
+ this.sqlTypeName = sqlTypeName;
+ this.sqlType = sqlType;
+ this.clazz = clazz;
+ this.clazzNameBytes = Bytes.toBytes(clazz.getName());
+ this.sqlTypeNameBytes = Bytes.toBytes(sqlTypeName);
+ this.codec = codec;
+ this.ordinal = ordinal;
+ }
+
+ @Deprecated
+ public static PDataType[] values() {
+ return PDataTypeFactory.getInstance().getOrderedTypes();
+ }
+
+ @Deprecated
+ public int ordinal() {
+ return ordinal;
+ }
+
+ @Override
+ public Class<T> encodedClass() {
+ return getJavaClass();
+ }
+
+ public boolean isCastableTo(PDataType targetType) {
+ return isComparableTo(targetType);
+ }
+
+ public final PDataCodec getCodec() {
+ return codec;
+ }
+
+ public boolean isBytesComparableWith(PDataType otherType) {
+ return this == otherType || this.getClass() == PVarbinary.class || otherType == PVarbinary.INSTANCE
+ || this.getClass() == PBinary.class || otherType == PBinary.INSTANCE;
+ }
+
+ public int estimateByteSize(Object o) {
+ if (isFixedWidth()) { return getByteSize(); }
+ if (isArrayType()) {
+ PhoenixArray array = (PhoenixArray)o;
+ int noOfElements = array.numElements;
+ int totalVarSize = 0;
+ for (int i = 0; i < noOfElements; i++) {
+ totalVarSize += array.estimateByteSize(i);
+ }
+ return totalVarSize;
+ }
+ // Non fixed width types must override this
+ throw new UnsupportedOperationException();
+ }
+
+ public Integer getMaxLength(Object o) {
+ return null;
+ }
+
+ public Integer getScale(Object o) {
+ return null;
+ }
+
+ /**
+ * Estimate the byte size from the type length. For example, for char, byte size would be the same as length. For
+ * decimal, byte size would have no correlation with the length.
+ */
+ public Integer estimateByteSizeFromLength(Integer length) {
+ if (isFixedWidth()) { return getByteSize(); }
+ if (isArrayType()) { return null; }
+ // If not fixed width, default to say the byte size is the same as length.
+ return length;
+ }
+
+ public final String getSqlTypeName() {
+ return sqlTypeName;
+ }
+
+ public final int getSqlType() {
+ return sqlType;
+ }
+
+ public final Class getJavaClass() {
+ return clazz;
+ }
+
+ public boolean isArrayType() {
+ return false;
+ }
- @Override
- public boolean equals(Object o) {
- // PDataType's are expected to be singletons.
- // TODO: this doesn't jive with HBase's DataType
- if (o == null) return false;
- return getClass() == o.getClass();
- }
+ public final int compareTo(byte[] lhs, int lhsOffset, int lhsLength, SortOrder lhsSortOrder, byte[] rhs,
+ int rhsOffset, int rhsLength, SortOrder rhsSortOrder, PDataType rhsType) {
+ Preconditions.checkNotNull(lhsSortOrder);
+ Preconditions.checkNotNull(rhsSortOrder);
+ if (this.isBytesComparableWith(rhsType)) { // directly compare the bytes
+ // Special case as we may be comparing two arrays that have different separator characters due to PHOENIX-2067
+ if (!this.isArrayType() || !rhsType.isArrayType() ||
+ PArrayDataType.isRowKeyOrderOptimized(this, lhsSortOrder, lhs, lhsOffset, lhsLength) == PArrayDataType.isRowKeyOrderOptimized(rhsType, rhsSortOrder, rhs, rhsOffset, rhsLength)) {
+ return compareTo(lhs, lhsOffset, lhsLength, lhsSortOrder, rhs, rhsOffset, rhsLength, rhsSortOrder);
+ }
+ }
+ PDataCodec lhsCodec = this.getCodec();
+ if ( lhsCodec == null ) {
+ byte[] rhsConverted;
+ Object o = this.toObject(rhs, rhsOffset, rhsLength, rhsType, rhsSortOrder);
+
+ // No lhs native type representation, so convert rhsType to bytes representation of lhs type
+ // Due to PHOENIX-2067, favor the array that is already in the new format so we don't have to convert both.
+ if ( this.isArrayType() && PArrayDataType.isRowKeyOrderOptimized(this, lhsSortOrder, lhs, lhsOffset, lhsLength) == PArrayDataType.isRowKeyOrderOptimized(rhsType, rhsSortOrder, rhs, rhsOffset, rhsLength)) {
+ rhsConverted = ((PArrayDataType)this).toBytes(o, PArrayDataType.arrayBaseType(this), lhsSortOrder, PArrayDataType.isRowKeyOrderOptimized(this, lhsSortOrder, lhs, lhsOffset, lhsLength));
+ } else {
+ rhsConverted = this.toBytes(o);
+ if (rhsSortOrder == SortOrder.DESC) {
+ rhsSortOrder = SortOrder.ASC;
+ }
+ if (lhsSortOrder == SortOrder.DESC) {
+ lhs = SortOrder.invert(lhs, lhsOffset, new byte[lhsLength], 0, lhsLength);
+ }
+ }
+ return Bytes.compareTo(lhs, lhsOffset, lhsLength, rhsConverted, 0, rhsConverted.length);
+ }
+ PDataCodec rhsCodec = rhsType.getCodec();
+ if (rhsCodec == null) {
+ byte[] lhsConverted;
+ Object o = rhsType.toObject(lhs, lhsOffset, lhsLength, this, lhsSortOrder);
+
+ // No rhs native type representation, so convert lhsType to bytes representation of rhs type
+ // Due to PHOENIX-2067, favor the array that is already in the new format so we don't have to convert both.
+ if ( rhsType.isArrayType() && PArrayDataType.isRowKeyOrderOptimized(rhsType, rhsSortOrder, rhs, rhsOffset, rhsLength) == PArrayDataType.isRowKeyOrderOptimized(this, lhsSortOrder, lhs, lhsOffset, lhsLength)) {
+ lhsConverted = ((PArrayDataType)rhsType).toBytes(o, PArrayDataType.arrayBaseType(rhsType), rhsSortOrder, PArrayDataType.isRowKeyOrderOptimized(rhsType, rhsSortOrder, rhs, rhsOffset, rhsLength));
+ } else {
+ lhsConverted = rhsType.toBytes(o);
+ if (lhsSortOrder == SortOrder.DESC) {
+ lhsSortOrder = SortOrder.ASC;
+ }
+ if (rhsSortOrder == SortOrder.DESC) {
+ rhs = SortOrder.invert(rhs, rhsOffset, new byte[rhsLength], 0, rhsLength);
+ }
+ }
+ return Bytes.compareTo(lhsConverted, 0, lhsConverted.length, rhs, rhsOffset, rhsLength);
+ }
+ // convert to native and compare
+ if (this.isCoercibleTo(PLong.INSTANCE) && rhsType.isCoercibleTo(PLong.INSTANCE)) { // native long to long
+ // comparison
+ return Longs.compare(this.getCodec().decodeLong(lhs, lhsOffset, lhsSortOrder), rhsType.getCodec()
+ .decodeLong(rhs, rhsOffset, rhsSortOrder));
+ } else if (isDoubleOrFloat(this) && isDoubleOrFloat(rhsType)) { // native double to double comparison
+ return Doubles.compare(this.getCodec().decodeDouble(lhs, lhsOffset, lhsSortOrder), rhsType.getCodec()
+ .decodeDouble(rhs, rhsOffset, rhsSortOrder));
+ } else { // native float/double to long comparison
+ float fvalue = 0.0F;
+ double dvalue = 0.0;
+ long lvalue = 0;
+ boolean isFloat = false;
+ int invert = 1;
+
+ if (this.isCoercibleTo(PLong.INSTANCE)) {
+ lvalue = this.getCodec().decodeLong(lhs, lhsOffset, lhsSortOrder);
+ } else if (this.getClass() == PFloat.class) {
+ isFloat = true;
+ fvalue = this.getCodec().decodeFloat(lhs, lhsOffset, lhsSortOrder);
+ } else if (this.isCoercibleTo(PDouble.INSTANCE)) {
+ dvalue = this.getCodec().decodeDouble(lhs, lhsOffset, lhsSortOrder);
+ }
+ if (rhsType.isCoercibleTo(PLong.INSTANCE)) {
+ lvalue = rhsType.getCodec().decodeLong(rhs, rhsOffset, rhsSortOrder);
+ } else if (rhsType == PFloat.INSTANCE) {
+ invert = -1;
+ isFloat = true;
+ fvalue = rhsType.getCodec().decodeFloat(rhs, rhsOffset, rhsSortOrder);
+ } else if (rhsType.isCoercibleTo(PDouble.INSTANCE)) {
+ invert = -1;
+ dvalue = rhsType.getCodec().decodeDouble(rhs, rhsOffset, rhsSortOrder);
+ }
+ // Invert the comparison if float/double value is on the RHS
+ return invert * (isFloat ? compareFloatToLong(fvalue, lvalue) : compareDoubleToLong(dvalue, lvalue));
+ }
+ }
- /**
- * @return true when {@code lhs} equals any of {@code rhs}.
- */
- public static boolean equalsAny(PDataType lhs, PDataType... rhs) {
- for (int i = 0; i < rhs.length; i++) {
- if (lhs.equals(rhs[i])) return true;
+ public static boolean isDoubleOrFloat(PDataType type) {
+ return type == PFloat.INSTANCE || type == PDouble.INSTANCE || type == PUnsignedFloat.INSTANCE
+ || type == PUnsignedDouble.INSTANCE;
}
- return false;
- }
- public static interface PDataCodec {
- public long decodeLong(ImmutableBytesWritable ptr, SortOrder sortOrder);
+ /**
+ * Compares a float against a long. Behaves better than {@link #compareDoubleToLong(double, long)} for float values
+ * outside of Integer.MAX_VALUE and Integer.MIN_VALUE.
+ *
+ * @param f
+ * a float value
+ * @param l
+ * a long value
+ * @return -1 if f is less than l, 1 if f is greater than l, and 0 if f is equal to l
+ */
+ private static int compareFloatToLong(float f, long l) {
+ if (f > Integer.MAX_VALUE || f < Integer.MIN_VALUE) { return f < l ? -1 : f > l ? 1 : 0; }
+ long diff = (long)f - l;
+ return Long.signum(diff);
+ }
- public long decodeLong(byte[] b, int o, SortOrder sortOrder);
+ /**
+ * Compares a double against a long.
+ *
+ * @param d
+ * a double value
+ * @param l
+ * a long value
+ * @return -1 if d is less than l, 1 if d is greater than l, and 0 if d is equal to l
+ */
+ private static int compareDoubleToLong(double d, long l) {
+ if (d > Long.MAX_VALUE) { return 1; }
+ if (d < Long.MIN_VALUE) { return -1; }
+ long diff = (long)d - l;
+ return Long.signum(diff);
+ }
- public int decodeInt(ImmutableBytesWritable ptr, SortOrder sortOrder);
+ protected static void checkForSufficientLength(byte[] b, int offset, int requiredLength) {
+ if (b.length < offset + requiredLength) { throw new RuntimeException(new SQLExceptionInfo.Builder(
+ SQLExceptionCode.ILLEGAL_DATA)
+ .setMessage("Expected length of at least " + requiredLength + " bytes, but had " + (b.length - offset))
+ .build().buildException()); }
+ }
- public int decodeInt(byte[] b, int o, SortOrder sortOrder);
+ protected static Void throwConstraintViolationException(PDataType source, PDataType target) {
+ throw new ConstraintViolationException(new SQLExceptionInfo.Builder(SQLExceptionCode.TYPE_MISMATCH)
+ .setMessage(source + " cannot be coerced to " + target).build().buildException());
+ }
- public byte decodeByte(ImmutableBytesWritable ptr, SortOrder sortOrder);
+ protected static RuntimeException newIllegalDataException() {
+ return new IllegalDataException(new SQLExceptionInfo.Builder(SQLExceptionCode.ILLEGAL_DATA).build()
+ .buildException());
+ }
- public byte decodeByte(byte[] b, int o, SortOrder sortOrder);
+ protected static RuntimeException newIllegalDataException(String msg) {
+ return new IllegalDataException(new SQLExceptionInfo.Builder(SQLExceptionCode.ILLEGAL_DATA).setMessage(msg)
+ .build().buildException());
+ }
- public short decodeShort(ImmutableBytesWritable ptr, SortOrder sortOrder);
+ protected static RuntimeException newIllegalDataException(Exception e) {
+ return new IllegalDataException(new SQLExceptionInfo.Builder(SQLExceptionCode.ILLEGAL_DATA).setRootCause(e)
+ .build().buildException());
+ }
- public short decodeShort(byte[] b, int o, SortOrder sortOrder);
+ @Override
+ public boolean equals(Object o) {
+ // PDataType's are expected to be singletons.
+ // TODO: this doesn't jive with HBase's DataType
+ if (o == null) return false;
+ return getClass() == o.getClass();
+ }
+
+ /**
+ * @return true when {@code lhs} equals any of {@code rhs}.
+ */
+ public static boolean equalsAny(PDataType lhs, PDataType... rhs) {
+ for (int i = 0; i < rhs.length; i++) {
+ if (lhs.equals(rhs[i])) return true;
+ }
+ return false;
+ }
- public float decodeFloat(ImmutableBytesWritable ptr, SortOrder sortOrder);
+ public static interface PDataCodec {
+ public long decodeLong(ImmutableBytesWritable ptr, SortOrder sortOrder);
- public float decodeFloat(byte[] b, int o, SortOrder sortOrder);
+ public long decodeLong(byte[] b, int o, SortOrder sortOrder);
- public double decodeDouble(ImmutableBytesWritable ptr, SortOrder sortOrder);
+ public int decodeInt(ImmutableBytesWritable ptr, SortOrder sortOrder);
- public double decodeDouble(byte[] b, int o, SortOrder sortOrder);
+ public int decodeInt(byte[] b, int o, SortOrder sortOrder);
- public int encodeLong(long v, ImmutableBytesWritable ptr);
+ public byte decodeByte(ImmutableBytesWritable ptr, SortOrder sortOrder);
- public int encodeLong(long v, byte[] b, int o);
+ public byte decodeByte(byte[] b, int o, SortOrder sortOrder);
- public int encodeInt(int v, ImmutableBytesWritable ptr);
+ public short decodeShort(ImmutableBytesWritable ptr, SortOrder sortOrder);
- public int encodeInt(int v, byte[] b, int o);
+ public short decodeShort(byte[] b, int o, SortOrder sortOrder);
- public int encodeByte(byte v, ImmutableBytesWritable ptr);
+ public float decodeFloat(ImmutableBytesWritable ptr, SortOrder sortOrder);
- public int encodeByte(byte v, byte[] b, int o);
+ public float decodeFloat(byte[] b, int o, SortOrder sortOrder);
- public int encodeShort(short v, ImmutableBytesWritable ptr);
+ public double decodeDouble(ImmutableBytesWritable ptr, SortOrder sortOrder);
- public int encodeShort(short v, byte[] b, int o);
+ public double decodeDouble(byte[] b, int o, SortOrder sortOrder);
- public int encodeFloat(float v, ImmutableBytesWritable ptr);
+ public int encodeLong(long v, ImmutableBytesWritable ptr);
- public int encodeFloat(float v, byte[] b, int o);
+ public int encodeLong(long v, byte[] b, int o);
- public int encodeDouble(double v, ImmutableBytesWritable ptr);
+ public int encodeInt(int v, ImmutableBytesWritable ptr);
- public int encodeDouble(double v, byte[] b, int o);
+ public int encodeInt(int v, byte[] b, int o);
- public PhoenixArrayFactory getPhoenixArrayFactory();
- }
+ public int encodeByte(byte v, ImmutableBytesWritable ptr);
- public static abstract class BaseCodec implements PDataCodec {
- @Override
- public int decodeInt(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- return decodeInt(ptr.get(), ptr.getOffset(), sortOrder);
+ public int encodeByte(byte v, byte[] b, int o);
+
+ public int encodeShort(short v, ImmutableBytesWritable ptr);
+
+ public int encodeShort(short v, byte[] b, int o);
+
+ public int encodeFloat(float v, ImmutableBytesWritable ptr);
+
+ public int encodeFloat(float v, byte[] b, int o);
+
+ public int encodeDouble(double v, ImmutableBytesWritable ptr);
+
+ public int encodeDouble(double v, byte[] b, int o);
+
+ public PhoenixArrayFactory getPhoenixArrayFactory();
}
- @Override
- public long decodeLong(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- return decodeLong(ptr.get(), ptr.getOffset(), sortOrder);
+ public static abstract class BaseCodec implements PDataCodec {
+ @Override
+ public int decodeInt(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ return decodeInt(ptr.get(), ptr.getOffset(), sortOrder);
+ }
+
+ @Override
+ public long decodeLong(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ return decodeLong(ptr.get(), ptr.getOffset(), sortOrder);
+ }
+
+ @Override
+ public byte decodeByte(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ return decodeByte(ptr.get(), ptr.getOffset(), sortOrder);
+ }
+
+ @Override
+ public short decodeShort(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ return decodeShort(ptr.get(), ptr.getOffset(), sortOrder);
+ }
+
+ @Override
+ public float decodeFloat(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ return decodeFloat(ptr.get(), ptr.getOffset(), sortOrder);
+ }
+
+ @Override
+ public float decodeFloat(byte[] b, int o, SortOrder sortOrder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public double decodeDouble(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ return decodeDouble(ptr.get(), ptr.getOffset(), sortOrder);
+ }
+
+ @Override
+ public double decodeDouble(byte[] b, int o, SortOrder sortOrder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int encodeInt(int v, ImmutableBytesWritable ptr) {
+ return encodeInt(v, ptr.get(), ptr.getOffset());
+ }
+
+ @Override
+ public int encodeLong(long v, ImmutableBytesWritable ptr) {
+ return encodeLong(v, ptr.get(), ptr.getOffset());
+ }
+
+ @Override
+ public int encodeByte(byte v, ImmutableBytesWritable ptr) {
+ return encodeByte(v, ptr.get(), ptr.getOffset());
+ }
+
+ @Override
+ public int encodeShort(short v, ImmutableBytesWritable ptr) {
+ return encodeShort(v, ptr.get(), ptr.getOffset());
+ }
+
+ @Override
+ public int encodeFloat(float v, ImmutableBytesWritable ptr) {
+ return encodeFloat(v, ptr.get(), ptr.getOffset());
+ }
+
+ @Override
+ public int encodeDouble(double v, ImmutableBytesWritable ptr) {
+ return encodeDouble(v, ptr.get(), ptr.getOffset());
+ }
+
+ @Override
+ public int encodeInt(int v, byte[] b, int o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int encodeLong(long v, byte[] b, int o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int encodeByte(byte v, byte[] b, int o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int encodeShort(short v, byte[] b, int o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int encodeFloat(float v, byte[] b, int o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int encodeDouble(double v, byte[] b, int o) {
+ throw new UnsupportedOperationException();
+ }
}
- @Override
- public byte decodeByte(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- return decodeByte(ptr.get(), ptr.getOffset(), sortOrder);
+ public static final int MAX_PRECISION = 38;
+ // Max precision guaranteed to fit into a long (and this should be plenty)
+ public static final int MIN_DECIMAL_AVG_SCALE = 4;
+ public static final MathContext DEFAULT_MATH_CONTEXT = new MathContext(MAX_PRECISION, RoundingMode.HALF_UP);
+ public static final int DEFAULT_SCALE = 0;
+
+ protected static final Integer MAX_BIG_DECIMAL_BYTES = 21;
+ protected static final Integer MAX_TIMESTAMP_BYTES = Bytes.SIZEOF_LONG + Bytes.SIZEOF_INT;
+
+ protected static final byte ZERO_BYTE = (byte)0x80;
+ protected static final byte NEG_TERMINAL_BYTE = (byte)102;
+ protected static final int EXP_BYTE_OFFSET = 65;
+ protected static final int POS_DIGIT_OFFSET = 1;
+ protected static final int NEG_DIGIT_OFFSET = 101;
+ protected static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
+ protected static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
+ protected static final long MAX_LONG_FOR_DESERIALIZE = Long.MAX_VALUE / 1000;
+ protected static final BigInteger ONE_HUNDRED = BigInteger.valueOf(100);
+
+ protected static final byte FALSE_BYTE = 0;
+ protected static final byte TRUE_BYTE = 1;
+ public static final byte[] FALSE_BYTES = new byte[] { FALSE_BYTE };
+ public static final byte[] TRUE_BYTES = new byte[] { TRUE_BYTE };
+ public static final byte[] NULL_BYTES = ByteUtil.EMPTY_BYTE_ARRAY;
+ protected static final Integer BOOLEAN_LENGTH = 1;
+
+ public final static Integer ZERO = 0;
+ public final static Integer INT_PRECISION = 10;
+ public final static Integer LONG_PRECISION = 19;
+ public final static Integer SHORT_PRECISION = 5;
+ public final static Integer BYTE_PRECISION = 3;
+ public final static Integer DOUBLE_PRECISION = 15;
+
+ public static final int ARRAY_TYPE_BASE = 3000;
+ public static final String ARRAY_TYPE_SUFFIX = "ARRAY";
+
+ protected static final ThreadLocal<Random> RANDOM = new ThreadLocal<Random>() {
+ @Override
+ protected Random initialValue() {
+ return new Random();
+ }
+ };
+
+ /**
+ * Serialize a BigDecimal into a variable length byte array in such a way that it is binary comparable.
+ *
+ * @param v
+ * the BigDecimal
+ * @param result
+ * the byte array to contain the serialized bytes. Max size necessary would be 21 bytes.
+ * @param length
+ * the number of bytes required to store the big decimal. May be adjusted down if it exceeds
+ * {@link #MAX_BIG_DECIMAL_BYTES}
+ * @return the number of bytes that make up the serialized BigDecimal
+ */
+ protected static int toBytes(BigDecimal v, byte[] result, final int offset, int length) {
+ // From scale to exponent byte (if BigDecimal is positive): (-(scale+(scale % 2 == 0 : 0 : 1)) / 2 + 65) | 0x80
+ // If scale % 2 is 1 (i.e. it's odd), then multiple last base-100 digit by 10
+ // For example: new BigDecimal(BigInteger.valueOf(1), -4);
+ // (byte)((-(-4+0) / 2 + 65) | 0x80) = -61
+ // From scale to exponent byte (if BigDecimal is negative): ~(-(scale+1)/2 + 65 + 128) & 0x7F
+ // For example: new BigDecimal(BigInteger.valueOf(1), 2);
+ // ~(-2/2 + 65 + 128) & 0x7F = 63
+ int signum = v.signum();
+ if (signum == 0) {
+ result[offset] = ZERO_BYTE;
+ return 1;
+ }
+ int index = offset + length;
+ int scale = v.scale();
+ int expOffset = scale % 2 * (scale < 0 ? -1 : 1);
+ // In order to get twice as much of a range for scale, it
+ // is multiplied by 2. If the scale is an odd number, then
+ // the first digit is multiplied by 10 to make up for the
+ // scale being off by one.
+ int multiplyBy;
+ BigInteger divideBy;
+ if (expOffset == 0) {
+ multiplyBy = 1;
+ divideBy = ONE_HUNDRED;
+ } else {
+ multiplyBy = 10;
+ divideBy = BigInteger.TEN;
+ }
+ // Normalize the scale based on what is necessary to end up with a base 100 decimal (i.e. 10.123e3)
+ int digitOffset;
+ BigInteger compareAgainst;
+ if (signum == 1) {
+ digitOffset = POS_DIGIT_OFFSET;
+ compareAgainst = MAX_LONG;
+ scale -= (length - 2) * 2;
+ result[offset] = (byte)((-(scale + expOffset) / 2 + EXP_BYTE_OFFSET) | 0x80);
+ } else {
+ digitOffset = NEG_DIGIT_OFFSET;
+ compareAgainst = MIN_LONG;
+ // Scale adjustment shouldn't include terminal byte in length
+ scale -= (length - 2 - 1) * 2;
+ result[offset] = (byte)(~(-(scale + expOffset) / 2 + EXP_BYTE_OFFSET + 128) & 0x7F);
+ if (length <= MAX_BIG_DECIMAL_BYTES) {
+ result[--index] = NEG_TERMINAL_BYTE;
+ } else {
+ // Adjust length and offset down because we don't have enough room
+ length = MAX_BIG_DECIMAL_BYTES;
+ index = offset + length;
+ }
+ }
+ BigInteger bi = v.unscaledValue();
+ // Use BigDecimal arithmetic until we can fit into a long
+ while (bi.compareTo(compareAgainst) * signum > 0) {
+ BigInteger[] dandr = bi.divideAndRemainder(divideBy);
+ bi = dandr[0];
+ int digit = dandr[1].intValue();
+ result[--index] = (byte)(digit * multiplyBy + digitOffset);
+ multiplyBy = 1;
+ divideBy = ONE_HUNDRED;
+ }
+ long l = bi.longValue();
+ do {
+ long divBy = 100 / multiplyBy;
+ long digit = l % divBy;
+ l /= divBy;
+ result[--index] = (byte)(digit * multiplyBy + digitOffset);
+ multiplyBy = 1;
+ } while (l != 0);
+
+ return length;
}
- @Override
- public short decodeShort(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- return decodeShort(ptr.get(), ptr.getOffset(), sortOrder);
+ /**
+ * Deserialize a variable length byte array into a BigDecimal. Note that because of the normalization that gets done
+ * to the scale, if you roundtrip a BigDecimal, it may not be equal before and after. However, the before and after
+ * number will always compare to be equal (i.e. <nBefore>.compareTo(<nAfter>) == 0)
+ *
+ * @param bytes
+ * the bytes containing the number
+ * @param offset
+ * the offset into the byte array
+ * @param length
+ * the length of the serialized BigDecimal
+ * @return the BigDecimal value.
+ */
+ protected static BigDecimal toBigDecimal(byte[] bytes, int offset, int length) {
+ // From exponent byte back to scale: (<exponent byte> & 0x7F) - 65) * 2
+ // For example, (((-63 & 0x7F) - 65) & 0xFF) * 2 = 0
+ // Another example: ((-64 & 0x7F) - 65) * 2 = -2 (then swap the sign for the scale)
+ // If number is negative, going from exponent byte back to scale: (byte)((~<exponent byte> - 65 - 128) * 2)
+ // For example: new BigDecimal(new BigInteger("-1"), -2);
+ // (byte)((~61 - 65 - 128) * 2) = 2, so scale is -2
+ // Potentially, when switching back, the scale can be added by one and the trailing zero dropped
+ // For digits, just do a mod 100 on the BigInteger. Use long if BigInteger fits
+ if (length == 1 && bytes[offset] == ZERO_BYTE) { return BigDecimal.ZERO; }
+ int signum = ((bytes[offset] & 0x80) == 0) ? -1 : 1;
+ int scale;
+ int index;
+ int digitOffset;
+ long multiplier = 100L;
+ int begIndex = offset + 1;
+ if (signum == 1) {
+ scale = (byte)(((bytes[offset] & 0x7F) - 65) * -2);
+ index = offset + length;
+ digitOffset = POS_DIGIT_OFFSET;
+ } else {
+ scale = (byte)((~bytes[offset] - 65 - 128) * -2);
+ index = offset + length - (bytes[offset + length - 1] == NEG_TERMINAL_BYTE ? 1 : 0);
+ digitOffset = -NEG_DIGIT_OFFSET;
+ }
+ length = index - offset;
+ long l = signum * bytes[--index] - digitOffset;
+ if (l % 10 == 0) { // trailing zero
+ scale--; // drop trailing zero and compensate in the scale
+ l /= 10;
+ multiplier = 10;
+ }
+ // Use long arithmetic for as long as we can
+ while (index > begIndex) {
+ if (l >= MAX_LONG_FOR_DESERIALIZE || multiplier >= Long.MAX_VALUE / 100) {
+ multiplier = LongMath.divide(multiplier, 100L, RoundingMode.UNNECESSARY);
+ break; // Exit loop early so we don't overflow our multiplier
+ }
+ int digit100 = signum * bytes[--index] - digitOffset;
+ l += digit100 * multiplier;
+ multiplier = LongMath.checkedMultiply(multiplier, 100);
+ }
+
+ BigInteger bi;
+ // If still more digits, switch to BigInteger arithmetic
+ if (index > begIndex) {
+ bi = BigInteger.valueOf(l);
+ BigInteger biMultiplier = BigInteger.valueOf(multiplier).multiply(ONE_HUNDRED);
+ do {
+ int digit100 = signum * bytes[--index] - digitOffset;
+ bi = bi.add(biMultiplier.multiply(BigInteger.valueOf(digit100)));
+ biMultiplier = biMultiplier.multiply(ONE_HUNDRED);
+ } while (index > begIndex);
+ if (signum == -1) {
+ bi = bi.negate();
+ }
+ } else {
+ bi = BigInteger.valueOf(l * signum);
+ }
+ // Update the scale based on the precision
+ scale += (length - 2) * 2;
+ BigDecimal v = new BigDecimal(bi, scale);
+ return v;
}
- @Override
- public float decodeFloat(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- return decodeFloat(ptr.get(), ptr.getOffset(), sortOrder);
+ // Calculate the precision and scale of a raw decimal bytes. Returns the values as an int
+ // array. The first value is precision, the second value is scale.
+ // Default scope for testing
+ protected static int[] getDecimalPrecisionAndScale(byte[] bytes, int offset, int length) {
+ // 0, which should have no precision nor scale.
+ if (length == 1 && bytes[offset] == ZERO_BYTE) { return new int[] { 0, 0 }; }
+ int signum = ((bytes[offset] & 0x80) == 0) ? -1 : 1;
+ int scale;
+ int index;
+ int digitOffset;
+ if (signum == 1) {
+ scale = (byte)(((bytes[offset] & 0x7F) - 65) * -2);
+ index = offset + length;
+ digitOffset = POS_DIGIT_OFFSET;
+ } else {
+ scale = (byte)((~bytes[offset] - 65 - 128) * -2);
+ index = offset + length - (bytes[offset + length - 1] == NEG_TERMINAL_BYTE ? 1 : 0);
+ digitOffset = -NEG_DIGIT_OFFSET;
+ }
+ length = index - offset;
+ int precision = 2 * (length - 1);
+ int d = signum * bytes[--index] - digitOffset;
+ if (d % 10 == 0) { // trailing zero
+ // drop trailing zero and compensate in the scale and precision.
+ d /= 10;
+ scale--;
+ precision -= 1;
+ }
+ d = signum * bytes[offset + 1] - digitOffset;
+ if (d < 10) { // Leading single digit
+ // Compensate in the precision.
+ precision -= 1;
+ }
+ // Update the scale based on the precision
+ scale += (length - 2) * 2;
+ if (scale < 0) {
+ precision = precision - scale;
+ scale = 0;
+ }
+ return new int[] { precision, scale };
}
- @Override
- public float decodeFloat(byte[] b, int o, SortOrder sortOrder) {
- throw new UnsupportedOperationException();
+ public boolean isCoercibleTo(PDataType targetType) {
+ return this.equals(targetType) || targetType.equals(PVarbinary.INSTANCE);
}
- @Override
- public double decodeDouble(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- return decodeDouble(ptr.get(), ptr.getOffset(), sortOrder);
+ // Specialized on enums to take into account type hierarchy (i.e. UNSIGNED_LONG is comparable to INTEGER)
+ public boolean isComparableTo(PDataType targetType) {
+ return targetType.isCoercibleTo(this) || this.isCoercibleTo(targetType);
}
- @Override
- public double decodeDouble(byte[] b, int o, SortOrder sortOrder) {
- throw new UnsupportedOperationException();
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ return isCoercibleTo(targetType);
}
- @Override
- public int encodeInt(int v, ImmutableBytesWritable ptr) {
- return encodeInt(v, ptr.get(), ptr.getOffset());
+ public boolean isSizeCompatible(ImmutableBytesWritable ptr, Object value, PDataType srcType, Integer maxLength,
+ Integer scale, Integer desiredMaxLength, Integer desiredScale) {
+ return true;
}
- @Override
- public int encodeLong(long v, ImmutableBytesWritable ptr) {
- return encodeLong(v, ptr.get(), ptr.getOffset());
+ public int compareTo(byte[] b1, byte[] b2) {
+ return compareTo(b1, 0, b1.length, SortOrder.getDefault(), b2, 0, b2.length, SortOrder.getDefault());
}
- @Override
- public int encodeByte(byte v, ImmutableBytesWritable ptr) {
- return encodeByte(v, ptr.get(), ptr.getOffset());
+ public final int compareTo(ImmutableBytesWritable ptr1, ImmutableBytesWritable ptr2) {
+ return compareTo(ptr1.get(), ptr1.getOffset(), ptr1.getLength(), SortOrder.getDefault(), ptr2.get(),
+ ptr2.getOffset(), ptr2.getLength(), SortOrder.getDefault());
+ }
+
+ public final int compareTo(byte[] ba1, int offset1, int length1, SortOrder so1, byte[] ba2, int offset2,
+ int length2, SortOrder so2) {
+ Preconditions.checkNotNull(so1);
+ Preconditions.checkNotNull(so2);
+ if (so1 != so2) {
+ int length = Math.min(length1, length2);
+ for (int i = 0; i < length; i++) {
+ byte b1 = ba1[offset1 + i];
+ byte b2 = ba2[offset2 + i];
+ if (so1 == SortOrder.DESC) {
+ b1 = SortOrder.invert(b1);
+ } else {
+ b2 = SortOrder.invert(b2);
+ }
+ int c = b1 - b2;
+ if (c != 0) { return c; }
+ }
+ return (length1 - length2);
+ }
+ return Bytes.compareTo(ba1, offset1, length1, ba2, offset2, length2) * (so1 == SortOrder.DESC ? -1 : 1);
+ }
+
+ public final int compareTo(ImmutableBytesWritable ptr1, SortOrder ptr1SortOrder, ImmutableBytesWritable ptr2,
+ SortOrder ptr2SortOrder, PDataType type2) {
+ return compareTo(ptr1.get(), ptr1.getOffset(), ptr1.getLength(), ptr1SortOrder, ptr2.get(), ptr2.getOffset(),
+ ptr2.getLength(), ptr2SortOrder, type2);
+ }
+
+ public int compareTo(Object lhs, Object rhs) {
+ return compareTo(lhs, rhs, this);
+ }
+
+ /*
+ * We need an empty byte array to mean null, since we have no other representation in the row key for null.
+ */
+ public final boolean isNull(byte[] value) {
+ return value == null || value.length == 0;
+ }
+
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ Preconditions.checkNotNull(sortOrder);
+ byte[] bytes = toBytes(object);
+ if (sortOrder == SortOrder.DESC) {
+ SortOrder.invert(bytes, 0, bytes, 0, bytes.length);
+ }
+ return bytes;
+ }
+
+ public void coerceBytes(ImmutableBytesWritable ptr, Object o, PDataType actualType, Integer actualMaxLength,
+ Integer actualScale, SortOrder actualModifier, Integer desiredMaxLength, Integer desiredScale,
+ SortOrder expectedModifier, boolean expectedRowKeyOrderOptimizable) {
+ coerceBytes(ptr, o, actualType, actualMaxLength, actualScale, actualModifier, desiredMaxLength, desiredScale,
+ expectedModifier);
+ }
+
+ public void coerceBytes(ImmutableBytesWritable ptr, Object o, PDataType actualType, Integer actualMaxLength,
+ Integer actualScale, SortOrder actualModifier, Integer desiredMaxLength, Integer desiredScale,
+ SortOrder expectedModifier) {
+ Preconditions.checkNotNull(actualModifier);
+ Preconditions.checkNotNull(expectedModifier);
+ if (ptr.getLength() == 0) { return; }
+ if (this.isBytesComparableWith(actualType)) { // No coerce necessary
+ if (actualModifier == expectedModifier) { return; }
+ byte[] b = ptr.copyBytes();
+ SortOrder.invert(b, 0, b, 0, b.length);
+ ptr.set(b);
+ return;
+ }
+
+ // Optimization for cases in which we already have the object around
+ if (o == null) {
+ o = actualType.toObject(ptr, actualType, actualModifier);
+ }
+
+ o = toObject(o, actualType);
+ byte[] b = toBytes(o, expectedModifier);
+ ptr.set(b);
+ }
+
+ public final void coerceBytes(ImmutableBytesWritable ptr, PDataType actualType, SortOrder actualModifier,
+ SortOrder expectedModifier) {
+ coerceBytes(ptr, null, actualType, null, null, actualModifier, null, null, expectedModifier);
+ }
+
+ public final void coerceBytes(ImmutableBytesWritable ptr, PDataType actualType, SortOrder actualModifier,
+ SortOrder expectedModifier, Integer desiredMaxLength) {
+ coerceBytes(ptr, null, actualType, null, null, actualModifier, desiredMaxLength, null, expectedModifier);
+ }
+
+ protected static boolean isNonNegativeDate(java.util.Date date) {
+ return (date == null || date.getTime() >= 0);
+ }
+
+ protected static void throwIfNonNegativeDate(java.util.Date date) {
+ if (!isNonNegativeDate(date)) { throw newIllegalDataException("Value may not be negative(" + date + ")"); }
+ }
+
+ protected static boolean isNonNegativeNumber(Number v) {
+ return v == null || v.longValue() >= 0;
+ }
+
+ protected static void throwIfNonNegativeNumber(Number v) {
+ if (!isNonNegativeNumber(v)) { throw newIllegalDataException("Value may not be negative(" + v + ")"); }
}
@Override
- public int encodeShort(short v, ImmutableBytesWritable ptr) {
- return encodeShort(v, ptr.get(), ptr.getOffset());
+ public boolean isNullable() {
+ return false;
}
+ public abstract Integer getByteSize();
+
@Override
- public int encodeFloat(float v, ImmutableBytesWritable ptr) {
- return encodeFloat(v, ptr.get(), ptr.getOffset());
+ public int encodedLength(T val) {
+ // default implementation based on existing PDataType methods.
+ return getByteSize();
}
@Override
- public int encodeDouble(double v, ImmutableBytesWritable ptr) {
- return encodeDouble(v, ptr.get(), ptr.getOffset());
+ public int skip(PositionedByteRange pbr) {
+ // default implementation based on existing PDataType methods.
+ int len = getByteSize();
+ pbr.setPosition(pbr.getPosition() + len);
+ return len;
}
@Override
- public int encodeInt(int v, byte[] b, int o) {
- throw new UnsupportedOperationException();
+ public boolean isOrderPreserving() {
+ return true;
}
@Override
- public int encodeLong(long v, byte[] b, int o) {
- throw new UnsupportedOperationException();
+ public boolean isSkippable() {
+ return true;
}
@Override
- public int encodeByte(byte v, byte[] b, int o) {
- throw new UnsupportedOperationException();
+ public Order getOrder() {
+ return Order.ASCENDING;
}
+ public abstract boolean isFixedWidth();
+
+ public abstract int compareTo(Object lhs, Object rhs, PDataType rhsType);
+
@Override
- public int encodeShort(short v, byte[] b, int o) {
- throw new UnsupportedOperationException();
+ public int compareTo(PDataType<?> other) {
+ return Integer.compare(this.ordinal(), other.ordinal());
}
+ /**
+ * Convert from the object representation of a data type value into the serialized byte form.
+ *
+ * @param object
+ * the object to convert
+ * @param bytes
+ * the byte array into which to put the serialized form of object
+ * @param offset
+ * the offset from which to start writing the serialized form
+ * @return the byte length of the serialized object
+ */
+ public abstract int toBytes(Object object, byte[] bytes, int offset);
+
@Override
- public int encodeFloat(float v, byte[] b, int o) {
- throw new UnsupportedOperationException();
+ public int encode(PositionedByteRange pbr, T val) {
+ // default implementation based on existing PDataType methods.
+ int pos = pbr.getPosition();
+ pbr.put(toBytes(val));
+ return pbr.getPosition() - pos;
}
@Override
- public int encodeDouble(double v, byte[] b, int o) {
- throw new UnsupportedOperationException();
- }
- }
-
- public static final int MAX_PRECISION = 38;
- // Max precision guaranteed to fit into a long (and this should be plenty)
- public static final int MIN_DECIMAL_AVG_SCALE = 4;
- public static final MathContext DEFAULT_MATH_CONTEXT =
- new MathContext(MAX_PRECISION, RoundingMode.HALF_UP);
- public static final int DEFAULT_SCALE = 0;
-
- protected static final Integer MAX_BIG_DECIMAL_BYTES = 21;
- protected static final Integer MAX_TIMESTAMP_BYTES = Bytes.SIZEOF_LONG + Bytes.SIZEOF_INT;
-
- protected static final byte ZERO_BYTE = (byte) 0x80;
- protected static final byte NEG_TERMINAL_BYTE = (byte) 102;
- protected static final int EXP_BYTE_OFFSET = 65;
- protected static final int POS_DIGIT_OFFSET = 1;
- protected static final int NEG_DIGIT_OFFSET = 101;
- protected static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
- protected static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
- protected static final long MAX_LONG_FOR_DESERIALIZE = Long.MAX_VALUE / 1000;
- protected static final BigInteger ONE_HUNDRED = BigInteger.valueOf(100);
-
- protected static final byte FALSE_BYTE = 0;
- protected static final byte TRUE_BYTE = 1;
- public static final byte[] FALSE_BYTES = new byte[] { FALSE_BYTE };
- public static final byte[] TRUE_BYTES = new byte[] { TRUE_BYTE };
- public static final byte[] NULL_BYTES = ByteUtil.EMPTY_BYTE_ARRAY;
- protected static final Integer BOOLEAN_LENGTH = 1;
-
- public final static Integer ZERO = 0;
- public final static Integer INT_PRECISION = 10;
- public final static Integer LONG_PRECISION = 19;
- public final static Integer SHORT_PRECISION = 5;
- public final static Integer BYTE_PRECISION = 3;
- public final static Integer DOUBLE_PRECISION = 15;
-
- public static final int ARRAY_TYPE_BASE = 3000;
- public static final String ARRAY_TYPE_SUFFIX = "ARRAY";
-
- protected static final ThreadLocal<Random> RANDOM = new ThreadLocal<Random>() {
+ public String toString() {
+ return sqlTypeName;
+ }
+
+ public abstract byte[] toBytes(Object object);
+
+ /**
+ * Convert from a string to the object representation of a given type
+ *
+ * @param value
+ * a stringified value
+ * @return the object representation of a string value
+ */
+ public abstract Object toObject(String value);
+
+ /*
+ * Each enum must override this to define the set of object it may be coerced to
+ */
+ public abstract Object toObject(Object object, PDataType actualType);
+
+ /*
+ * Each enum must override this to define the set of objects it may create
+ */
+ public abstract Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder,
+ Integer maxLength, Integer scale);
+
@Override
- protected Random initialValue() {
- return new Random();
- }
- };
-
- /**
- * Serialize a BigDecimal into a variable length byte array in such a way that it is
- * binary comparable.
- *
- * @param v the BigDecimal
- * @param result the byte array to contain the serialized bytes. Max size
- * necessary would be 21 bytes.
- * @param length the number of bytes required to store the big decimal. May be
- * adjusted down if it exceeds {@link #MAX_BIG_DECIMAL_BYTES}
- * @return the number of bytes that make up the serialized BigDecimal
- */
- protected static int toBytes(BigDecimal v, byte[] result, final int offset, int length) {
- // From scale to exponent byte (if BigDecimal is positive): (-(scale+(scale % 2 == 0 : 0 : 1)) / 2 + 65) | 0x80
- // If scale % 2 is 1 (i.e. it's odd), then multiple last base-100 digit by 10
- // For example: new BigDecimal(BigInteger.valueOf(1), -4);
- // (byte)((-(-4+0) / 2 + 65) | 0x80) = -61
- // From scale to exponent byte (if BigDecimal is negative): ~(-(scale+1)/2 + 65 + 128) & 0x7F
- // For example: new BigDecimal(BigInteger.valueOf(1), 2);
- // ~(-2/2 + 65 + 128) & 0x7F = 63
- int signum = v.signum();
- if (signum == 0) {
- result[offset] = ZERO_BYTE;
- return 1;
- }
- int index = offset + length;
- int scale = v.scale();
- int expOffset = scale % 2 * (scale < 0 ? -1 : 1);
- // In order to get twice as much of a range for scale, it
- // is multiplied by 2. If the scale is an odd number, then
- // the first digit is multiplied by 10 to make up for the
- // scale being off by one.
- int multiplyBy;
- BigInteger divideBy;
- if (expOffset == 0) {
- multiplyBy = 1;
- divideBy = ONE_HUNDRED;
- } else {
- multiplyBy = 10;
- divideBy = BigInteger.TEN;
- }
- // Normalize the scale based on what is necessary to end up with a base 100 decimal (i.e. 10.123e3)
- int digitOffset;
- BigInteger compareAgainst;
- if (signum == 1) {
- digitOffset = POS_DIGIT_OFFSET;
- compareAgainst = MAX_LONG;
- scale -= (length - 2) * 2;
- result[offset] = (byte) ((-(scale + expOffset) / 2 + EXP_BYTE_OFFSET) | 0x80);
- } else {
- digitOffset = NEG_DIGIT_OFFSET;
- compareAgainst = MIN_LONG;
- // Scale adjustment shouldn't include terminal byte in length
- scale -= (length - 2 - 1) * 2;
- result[offset] = (byte) (~(-(scale + expOffset) / 2 + EXP_BYTE_OFFSET + 128) & 0x7F);
- if (length <= MAX_BIG_DECIMAL_BYTES) {
- result[--index] = NEG_TERMINAL_BYTE;
- } else {
- // Adjust length and offset down because we don't have enough room
- length = MAX_BIG_DECIMAL_BYTES;
- index = offset + length;
- }
- }
- BigInteger bi = v.unscaledValue();
- // Use BigDecimal arithmetic until we can fit into a long
- while (bi.compareTo(compareAgainst) * signum > 0) {
- BigInteger[] dandr = bi.divideAndRemainder(divideBy);
- bi = dandr[0];
- int digit = dandr[1].intValue();
- result[--index] = (byte) (digit * multiplyBy + digitOffset);
- multiplyBy = 1;
- divideBy = ONE_HUNDRED;
- }
- long l = bi.longValue();
- do {
- long divBy = 100 / multiplyBy;
- long digit = l % divBy;
- l /= divBy;
- result[--index] = (byte) (digit * multiplyBy + digitOffset);
- multiplyBy = 1;
- } while (l != 0);
-
- return length;
- }
-
- /**
- * Deserialize a variable length byte array into a BigDecimal. Note that because of
- * the normalization that gets done to the scale, if you roundtrip a BigDecimal,
- * it may not be equal before and after. However, the before and after number will
- * always compare to be equal (i.e. <nBefore>.compareTo(<nAfter>) == 0)
- *
- * @param bytes the bytes containing the number
- * @param offset the offset into the byte array
- * @param length the length of the serialized BigDecimal
- * @return the BigDecimal value.
- */
- protected static BigDecimal toBigDecimal(byte[] bytes, int offset, int length) {
- // From exponent byte back to scale: (<exponent byte> & 0x7F) - 65) * 2
- // For example, (((-63 & 0x7F) - 65) & 0xFF) * 2 = 0
- // Another example: ((-64 & 0x7F) - 65) * 2 = -2 (then swap the sign for the scale)
- // If number is negative, going from exponent byte back to scale: (byte)((~<exponent byte> - 65 - 128) * 2)
- // For example: new BigDecimal(new BigInteger("-1"), -2);
- // (byte)((~61 - 65 - 128) * 2) = 2, so scale is -2
- // Potentially, when switching back, the scale can be added by one and the trailing zero dropped
- // For digits, just do a mod 100 on the BigInteger. Use long if BigInteger fits
- if (length == 1 && bytes[offset] == ZERO_BYTE) {
- return BigDecimal.ZERO;
- }
- int signum = ((bytes[offset] & 0x80) == 0) ? -1 : 1;
- int scale;
- int index;
- int digitOffset;
- long multiplier = 100L;
- int begIndex = offset + 1;
- if (signum == 1) {
- scale = (byte) (((bytes[offset] & 0x7F) - 65) * -2);
- index = offset + length;
- digitOffset = POS_DIGIT_OFFSET;
- } else {
- scale = (byte) ((~bytes[offset] - 65 - 128) * -2);
- index = offset + length - (bytes[offset + length - 1] == NEG_TERMINAL_BYTE ? 1 : 0);
- digitOffset = -NEG_DIGIT_OFFSET;
- }
- length = index - offset;
- long l = signum * bytes[--index] - digitOffset;
- if (l % 10 == 0) { // trailing zero
- scale--; // drop trailing zero and compensate in the scale
- l /= 10;
- multiplier = 10;
- }
- // Use long arithmetic for as long as we can
- while (index > begIndex) {
- if (l >= MAX_LONG_FOR_DESERIALIZE || multiplier >= Long.MAX_VALUE / 100) {
- multiplier = LongMath.divide(multiplier, 100L, RoundingMode.UNNECESSARY);
- break; // Exit loop early so we don't overflow our multiplier
- }
- int digit100 = signum * bytes[--index] - digitOffset;
- l += digit100 * multiplier;
- multiplier = LongMath.checkedMultiply(multiplier, 100);
- }
-
- BigInteger bi;
- // If still more digits, switch to BigInteger arithmetic
- if (index > begIndex) {
- bi = BigInteger.valueOf(l);
- BigInteger biMultiplier = BigInteger.valueOf(multiplier).multiply(ONE_HUNDRED);
- do {
- int digit100 = signum * bytes[--index] - digitOffset;
- bi = bi.add(biMultiplier.multiply(BigInteger.valueOf(digit100)));
- biMultiplier = biMultiplier.multiply(ONE_HUNDRED);
- } while (index > begIndex);
- if (signum == -1) {
- bi = bi.negate();
- }
- } else {
- bi = BigInteger.valueOf(l * signum);
- }
- // Update the scale based on the precision
- scale += (length - 2) * 2;
- BigDecimal v = new BigDecimal(bi, scale);
- return v;
- }
-
- // Calculate the precision and scale of a raw decimal bytes. Returns the values as an int
- // array. The first value is precision, the second value is scale.
- // Default scope for testing
- protected static int[] getDecimalPrecisionAndScale(byte[] bytes, int offset, int length) {
- // 0, which should have no precision nor scale.
- if (length == 1 && bytes[offset] == ZERO_BYTE) {
- return new int[] { 0, 0 };
- }
- int signum = ((bytes[offset] & 0x80) == 0) ? -1 : 1;
- int scale;
- int index;
- int digitOffset;
- if (signum == 1) {
- scale = (byte) (((bytes[offset] & 0x7F) - 65) * -2);
- index = offset + length;
- digitOffset = POS_DIGIT_OFFSET;
- } else {
- scale = (byte) ((~bytes[offset] - 65 - 128) * -2);
- index = offset + length - (bytes[offset + length - 1] == NEG_TERMINAL_BYTE ? 1 : 0);
- digitOffset = -NEG_DIGIT_OFFSET;
- }
- length = index - offset;
- int precision = 2 * (length - 1);
- int d = signum * bytes[--index] - digitOffset;
- if (d % 10 == 0) { // trailing zero
- // drop trailing zero and compensate in the scale and precision.
- d /= 10;
- scale--;
- precision -= 1;
- }
- d = signum * bytes[offset + 1] - digitOffset;
- if (d < 10) { // Leading single digit
- // Compensate in the precision.
- precision -= 1;
- }
- // Update the scale based on the precision
- scale += (length - 2) * 2;
- if (scale < 0) {
- precision = precision - scale;
- scale = 0;
- }
- return new int[] { precision, scale };
- }
-
- public boolean isCoercibleTo(PDataType targetType) {
- return this.equals(targetType) || targetType.equals(PVarbinary.INSTANCE);
- }
-
- // Specialized on enums to take into account type hierarchy (i.e. UNSIGNED_LONG is comparable to INTEGER)
- public boolean isComparableTo(PDataType targetType) {
- return targetType.isCoercibleTo(this) || this.isCoercibleTo(targetType);
- }
-
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- return isCoercibleTo(targetType);
- }
-
- public boolean isSizeCompatible(ImmutableBytesWritable ptr, Object value, PDataType srcType,
- Integer maxLength, Integer scale, Integer desiredMaxLength, Integer desiredScale) {
- return true;
- }
-
- public int compareTo(byte[] b1, byte[] b2) {
- return compareTo(b1, 0, b1.length, SortOrder.getDefault(), b2, 0, b2.length,
- SortOrder.getDefault());
- }
-
- public final int compareTo(ImmutableBytesWritable ptr1, ImmutableBytesWritable ptr2) {
- return compareTo(ptr1.get(), ptr1.getOffset(), ptr1.getLength(), SortOrder.getDefault(),
- ptr2.get(), ptr2.getOffset(), ptr2.getLength(), SortOrder.getDefault());
- }
-
- public final int compareTo(byte[] ba1, int offset1, int length1, SortOrder so1, byte[] ba2,
- int offset2, int length2, SortOrder so2) {
- Preconditions.checkNotNull(so1);
- Preconditions.checkNotNull(so2);
- if (so1 != so2) {
- int length = Math.min(length1, length2);
- for (int i = 0; i < length; i++) {
- byte b1 = ba1[offset1 + i];
- byte b2 = ba2[offset2 + i];
- if (so1 == SortOrder.DESC) {
- b1 = SortOrder.invert(b1);
- } else {
- b2 = SortOrder.invert(b2);
+ public T decode(PositionedByteRange pbr) {
+ // default implementation based on existing PDataType methods.
+ byte[] b = new byte[getByteSize()];
+ pbr.get(b);
+ return (T)toObject(b, 0, b.length, this, SortOrder.ASC, getMaxLength(null), getScale(null));
+ }
+
+ /*
+ * Return a valid object of this enum type
+ */
+ public abstract Object getSampleValue(Integer maxLength, Integer arrayLength);
+
+ public final Object getSampleValue() {
+ return getSampleValue(null);
+ }
+
+ public final Object getSampleValue(Integer maxLength) {
+ return getSampleValue(maxLength, null);
+ }
+
+ public final Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder) {
+ return toObject(bytes, offset, length, actualType, sortOrder, null, null);
+ }
+
+ public final Object toObject(byte[] bytes, int offset, int length, PDataType actualType) {
+ return toObject(bytes, offset, length, actualType, SortOrder.getDefault());
+ }
+
+ public final Object toObject(ImmutableBytesWritable ptr, PDataType actualType) {
+ return toObject(ptr, actualType, SortOrder.getDefault());
+ }
+
+ public final Object toObject(ImmutableBytesWritable ptr, PDataType actualType, SortOrder sortOrder) {
+ return this.toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), actualType, sortOrder);
+ }
+
+ public final Object toObject(ImmutableBytesWritable ptr, PDataType actualType, SortOrder sortOrder,
+ Integer maxLength, Integer scale) {
+ return this.toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), actualType, sortOrder, maxLength, scale);
+ }
+
+ public final Object toObject(ImmutableBytesWritable ptr, SortOrder sortOrder, Integer maxLength, Integer scale) {
+ return this.toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), this, sortOrder, maxLength, scale);
+ }
+
+ public final Object toObject(ImmutableBytesWritable ptr) {
+ return toObject(ptr.get(), ptr.getOffset(), ptr.getLength());
+ }
+
+ public final Object toObject(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ return toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), this, sortOrder);
+ }
+
+ public final Object toObject(byte[] bytes, int offset, int length) {
+ return toObject(bytes, offset, length, this);
+ }
+
+ public final Object toObject(byte[] bytes) {
+ return toObject(bytes, SortOrder.getDefault());
+ }
+
+ public final Object toObject(byte[] bytes, SortOrder sortOrder) {
+ return toObject(bytes, 0, bytes.length, this, sortOrder);
+ }
+
+ public final Object toObject(byte[] bytes, SortOrder sortOrder, PDataType actualType) {
+ return toObject(bytes, 0, bytes.length, actualType, sortOrder);
+ }
+
+ public static PDataType fromSqlTypeName(String sqlTypeName) {
+ for (PDataType t : PDataTypeFactory.getInstance().getTypes()) {
+ if (t.getSqlTypeName().equals(sqlTypeName)) return t;
}
- int c = b1 - b2;
- if (c != 0) {
- return c;
+ throw newIllegalDataException("Unsupported sql type: " + sqlTypeName);
+ }
+
+ public static int sqlArrayType(String sqlTypeName) {
+ PDataType fromSqlTypeName = fromSqlTypeName(sqlTypeName);
+ return fromSqlTypeName.getSqlType() + PDataType.ARRAY_TYPE_BASE;
+ }
+
+ protected static interface PhoenixArrayFactory {
+ PhoenixArray newArray(PDataType type, Object[] elements);
+ }
+
+ public static PDataType fromTypeId(int typeId) {
+ for (PDataType t : PDataTypeFactory.getInstance().getTypes()) {
+ if (t.getSqlType() == typeId) return t;
}
- }
- return (length1 - length2);
- }
- return Bytes.compareTo(ba1, offset1, length1, ba2, offset2, length2) * (so1 == SortOrder.DESC ?
- -1 :
- 1);
- }
-
- public final int compareTo(ImmutableBytesWritable ptr1, SortOrder ptr1SortOrder,
- ImmutableBytesWritable ptr2, SortOrder ptr2SortOrder, PDataType type2) {
- return compareTo(ptr1.get(), ptr1.getOffset(), ptr1.getLength(), ptr1SortOrder, ptr2.get(),
- ptr2.getOffset(), ptr2.getLength(), ptr2SortOrder, type2);
- }
-
- public int compareTo(Object lhs, Object rhs) {
- return compareTo(lhs, rhs, this);
- }
-
- /*
- * We need an empty byte array to mean null, since
- * we have no other representation in the row key
- * for null.
- */
- public final boolean isNull(byte[] value) {
- return value == null || value.length == 0;
- }
-
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- Preconditions.checkNotNull(sortOrder);
- byte[] bytes = toBytes(object);
- if (sortOrder == SortOrder.DESC) {
- SortOrder.invert(bytes, 0, bytes, 0, bytes.length);
- }
- return bytes;
- }
-
- public void coerceBytes(ImmutableBytesWritable ptr, Object o, PDataType actualType,
- Integer actualMaxLength, Integer actualScale, SortOrder actualModifier,
- Integer desiredMaxLength, Integer desiredScale, SortOrder expectedModifier) {
- Preconditions.checkNotNull(actualModifier);
- Preconditions.checkNotNull(expectedModifier);
- if (ptr.getLength() == 0) {
- return;
- }
- if (this.isBytesComparableWith(actualType)) { // No coerce necessary
- if (actualModifier == expectedModifier) {
- return;
- }
- byte[] b = ptr.copyBytes();
- SortOrder.invert(b, 0, b, 0, b.length);
- ptr.set(b);
- return;
- }
-
- // Optimization for cases in which we already have the object around
- if (o == null) {
- o = actualType.toObject(ptr, actualType, actualModifier);
- }
-
- o = toObject(o, actualType);
- byte[] b = toBytes(o, expectedModifier);
- ptr.set(b);
- }
-
- public final void coerceBytes(ImmutableBytesWritable ptr, PDataType actualType,
- SortOrder actualModifier, SortOrder expectedModifier) {
- coerceBytes(ptr, null, actualType, null, null, actualModifier, null, null, expectedModifier);
- }
-
- public final void coerceBytes(ImmutableBytesWritable ptr, PDataType actualType,
- SortOrder actualModifier,
- SortOrder expectedModifier, Integer desiredMaxLength) {
- coerceBytes(ptr, null, actualType, null, null, actualModifier, desiredMaxLength, null,
- expectedModifier);
- }
-
- protected static boolean isNonNegativeDate(java.util.Date date) {
- return (date == null || date.getTime() >= 0);
- }
-
- protected static void throwIfNonNegativeDate(java.util.Date date) {
- if (!isNonNegativeDate(date)) {
- throw newIllegalDataException("Value may not be negative(" + date + ")");
- }
- }
-
- protected static boolean isNonNegativeNumber(Number v) {
- return v == null || v.longValue() >= 0;
- }
-
- protected static void throwIfNonNegativeNumber(Number v) {
- if (!isNonNegativeNumber(v)) {
- throw newIllegalDataException("Value may not be negative(" + v + ")");
- }
- }
-
- @Override
- public boolean isNullable() {
- return false;
- }
-
- public abstract Integer getByteSize();
-
- @Override
- public int encodedLength(T val) {
- // default implementation based on existing PDataType methods.
- return getByteSize();
- }
-
- @Override
- public int skip(PositionedByteRange pbr) {
- // default implementation based on existing PDataType methods.
- int len = getByteSize();
- pbr.setPosition(pbr.getPosition() + len);
- return len;
- }
-
- @Override
- public boolean isOrderPreserving() {
- return true;
- }
-
- @Override
- public boolean isSkippable() {
- return true;
- }
-
- @Override
- public Order getOrder() {
- return Order.ASCENDING;
- }
-
- public abstract boolean isFixedWidth();
-
- public abstract int compareTo(Object lhs, Object rhs, PDataType rhsType);
-
- @Override
- public int compareTo(PDataType<?> other) {
- return Integer.compare(this.ordinal(), other.ordinal());
- }
-
- /**
- * Convert from the object representation of a data type value into
- * the serialized byte form.
- *
- * @param object the object to convert
- * @param bytes the byte array into which to put the serialized form of object
- * @param offset the offset from which to start writing the serialized form
- * @return the byte length of the serialized object
- */
- public abstract int toBytes(Object object, byte[] bytes, int offset);
-
- @Override
- public int encode(PositionedByteRange pbr, T val) {
- // default implementation based on existing PDataType methods.
- int pos = pbr.getPosition();
- pbr.put(toBytes(val));
- return pbr.getPosition() - pos;
- }
-
- @Override
- public String toString() {
- return sqlTypeName;
- }
-
- public abstract byte[] toBytes(Object object);
-
- /**
- * Convert from a string to the object representation of a given type
- *
- * @param value a stringified value
- * @return the object representation of a string value
- */
- public abstract Object toObject(String value);
-
- /*
- * Each enum must override this to define the set of object it may be coerced to
- */
- public abstract Object toObject(Object object, PDataType actualType);
-
- /*
- * Each enum must override this to define the set of objects it may create
- */
- public abstract Object toObject(byte[] bytes, int offset, int length, PDataType actualType,
- SortOrder sortOrder, Integer maxLength, Integer scale);
-
- @Override
- public T decode(PositionedByteRange pbr) {
- // default implementation based on existing PDataType methods.
- byte[] b = new byte[getByteSize()];
- pbr.get(b);
- return (T) toObject(b, 0, b.length, this, SortOrder.ASC, getMaxLength(null), getScale(null));
- }
-
- /*
- * Return a valid object of this enum type
+ throw newIllegalDataException("Unsupported sql type: " + typeId);
+ }
+
+ public String getJavaClassName() {
+ return getJavaClass().getName();
+ }
+
+ public byte[] getJavaClassNameBytes() {
+ return clazzNameBytes;
+ }
+
+ public byte[] getSqlTypeNameBytes() {
+ return sqlTypeNameBytes;
+ }
+
+ /**
+ * By default returns sqlType for the PDataType, however it allows unknown types (our unsigned types) to return the
+ * regular corresponding sqlType so that tools like SQuirrel correctly display values of this type.
+ *
+ * @return integer representing the SQL type for display of a result set of this type
*/
- public abstract Object getSampleValue(Integer maxLength, Integer arrayLength);
-
- public final Object getSampleValue() {
- return getSampleValue(null);
- }
-
- public final Object getSampleValue(Integer maxLength) {
- return getSampleValue(maxLength, null);
- }
-
- public final Object toObject(byte[] bytes, int offset, int length, PDataType actualType,
- SortOrder sortOrder) {
- return toObject(bytes, offset, length, actualType, sortOrder, null, null);
- }
-
- public final Object toObject(byte[] bytes, int offset, int length, PDataType actualType) {
- return toObject(bytes, offset, length, actualType, SortOrder.getDefault());
- }
-
- public final Object toObject(ImmutableBytesWritable ptr, PDataType actualType) {
- return toObject(ptr, actualType, SortOrder.getDefault());
- }
-
- public final Object toObject(ImmutableBytesWritable ptr, PDataType actualType,
- SortOrder sortOrder) {
- return this.toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), actualType, sortOrder);
- }
-
- public final Object toObject(ImmutableBytesWritable ptr, PDataType actualType,
- SortOrder sortOrder, Integer maxLength, Integer scale) {
- return this
- .toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), actualType, sortOrder, maxLength,
- scale);
- }
-
- public final Object toObject(ImmutableBytesWritable ptr, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return this
- .toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), this, sortOrder, maxLength, scale);
- }
-
- public final Object toObject(ImmutableBytesWritable ptr) {
- return toObject(ptr.get(), ptr.getOffset(), ptr.getLength());
- }
-
- public final Object toObject(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- return toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), this, sortOrder);
- }
-
- public final Object toObject(byte[] bytes, int offset, int length) {
- return toObject(bytes, offset, length, this);
- }
-
- public final Object toObject(byte[] bytes) {
- return toObject(bytes, SortOrder.getDefault());
- }
-
- public final Object toObject(byte[] bytes, SortOrder sortOrder) {
- return toObject(bytes, 0, bytes.length, this, sortOrder);
- }
-
- public final Object toObject(byte[] bytes, SortOrder sortOrder, PDataType actualType) {
- return toObject(bytes, 0, bytes.length, actualType, sortOrder);
- }
-
- public static PDataType fromSqlTypeName(String sqlTypeName) {
- for (PDataType t : PDataTypeFactory.getInstance().getTypes()) {
- if (t.getSqlTypeName().equals(sqlTypeName)) return t;
- }
- throw newIllegalDataException("Unsupported sql type: " + sqlTypeName);
- }
-
- public static int sqlArrayType(String sqlTypeName) {
- PDataType fromSqlTypeName = fromSqlTypeName(sqlTypeName);
- return fromSqlTypeName.getSqlType() + PDataType.ARRAY_TYPE_BASE;
- }
-
- protected static interface PhoenixArrayFactory {
- PhoenixArray newArray(PDataType type, Object[] elements);
- }
-
- public static PDataType fromTypeId(int typeId) {
- for (PDataType t : PDataTypeFactory.getInstance().getTypes()) {
- if (t.getSqlType() == typeId) return t;
- }
- throw newIllegalDataException("Unsupported sql type: " + typeId);
- }
-
- public String getJavaClassName() {
- return getJavaClass().getName();
- }
-
- public byte[] getJavaClassNameBytes() {
- return clazzNameBytes;
- }
-
- public byte[] getSqlTypeNameBytes() {
- return sqlTypeNameBytes;
- }
-
- /**
- * By default returns sqlType for the PDataType,
- * however it allows unknown types (our unsigned types)
- * to return the regular corresponding sqlType so
- * that tools like SQuirrel correctly display values
- * of this type.
- *
- * @return integer representing the SQL type for display
- * of a result set of this type
- */
- public int getResultSetSqlType() {
- return this.sqlType;
- }
-
- public KeyRange getKeyRange(byte[] point) {
- return getKeyRange(point, true, point, true);
- }
-
- public final String toStringLiteral(ImmutableBytesWritable ptr, Format formatter) {
- return toStringLiteral(ptr.get(), ptr.getOffset(), ptr.getLength(), formatter);
- }
-
- public final String toStringLiteral(byte[] b, Format formatter) {
- return toStringLiteral(b, 0, b.length, formatter);
- }
-
- public String toStringLiteral(byte[] b, int offset, int length, Format formatter) {
- Object o = toObject(b, offset, length);
- return toStringLiteral(o, formatter);
- }
-
+ public int getResultSetSqlType() {
+ return this.sqlType;
+ }
+
+ public KeyRange getKeyRange(byte[] point) {
+ return getKeyRange(point, true, point, true);
+ }
+
+ public final String toStringLiteral(ImmutableBytesWritable ptr, Format formatter) {
+ return toStringLiteral(ptr.get(), ptr.getOffset(), ptr.getLength(), formatter);
+ }
+
+ public final String toStringLiteral(byte[] b, Format formatter) {
+ return toStringLiteral(b, 0, b.length, formatter);
+ }
+
+ public String toStringLiteral(byte[] b, int offset, int length, Format formatter) {
+ Object o = toObject(b, offset, length);
+ return toStringLiteral(o, formatter);
+ }
+
public String toStringLiteral(Object o, Format formatter) {
if (formatter != null) {
return formatter.format(o);
- } else if (null == o) {
- return String.valueOf(o);
- }
+ } else if (null == o) { return String.valueOf(o); }
return o.toString();
}
@@ -1109,82 +1085,71 @@ public abstract class PDataType<T> implements DataType<T>, Comparable<PDataType<
return toStringLiteral(o, null);
}
- private static final PhoenixArrayFactory DEFAULT_ARRAY_FACTORY = new PhoenixArrayFactory() {
- @Override public PhoenixArray newArray(PDataType type, Object[] elements) {
- return new PhoenixArray(type, elements);
- }
- };
+ private static final PhoenixArrayFactory DEFAULT_ARRAY_FACTORY = new PhoenixArrayFactory() {
+ @Override
+ public PhoenixArray newArray(PDataType type, Object[] elements) {
+ return new PhoenixArray(type, elements);
+ }
+ };
- public PhoenixArrayFactory getArrayFactory() {
- if (getCodec() != null)
- return getCodec().getPhoenixArrayFactory();
- else
- return DEFAULT_ARRAY_FACTORY;
- }
+ public PhoenixArrayFactory getArrayFactory() {
+ if (getCodec() != null)
+ return getCodec().getPhoenixArrayFactory();
+ else
+ return DEFAULT_ARRAY_FACTORY;
+ }
- public static PhoenixArray instantiatePhoenixArray(PDataType actualType, Object[] elements) {
- return actualType.getArrayFactory().newArray(actualType, elements);
- }
+ public static PhoenixArray instantiatePhoenixArray(PDataType actualType, Object[] elements) {
+ return actualType.getArrayFactory().newArray(actualType, elements);
+ }
- public KeyRange getKeyRange(byte[] lowerRange, boolean lowerInclusive, byte[] upperRange,
- boolean upperInclusive) {
+ public KeyRange getKeyRange(byte[] lowerRange, boolean lowerInclusive, byte[] upperRange, boolean upperInclusive) {
/*
- * Force lower bound to be inclusive for fixed width keys because it makes
- * comparisons less expensive when you can count on one bound or the other
- * being inclusive. Comparing two fixed width exclusive bounds against each
- * other is inherently more expensive, because you need to take into account
- * if the bigger key is equal to the next key after the smaller key. For
- * example:
- * (A-B] compared against [A-B)
- * An exclusive lower bound A is bigger than an exclusive upper bound B.
- * Forcing a fixed width exclusive lower bound key to be inclusive prevents
- * us from having to do this extra logic in the compare function.
+ * Force lower bound to be inclusive for fixed width keys because it makes comparisons less expensive when you
+ * can count on one bound or the other being inclusive. Comparing two fixed width exclusive bounds against each
+ * other is inherently more expensive, because you need to take into account if the bigger key is equal to the
+ * next key after the smaller key. For example: (A-B] compared against [A-B) An exclusive lower bound A is
+ * bigger than an exclusive upper bound B. Forcing a fixed width exclusive lower bound key to be inclusive
+ * prevents us from having to do this extra logic in the compare function.
*/
- if (lowerRange != KeyRange.UNBOUND && !lowerInclusive && isFixedWidth()) {
- lowerRange = ByteUtil.nextKey(lowerRange);
- lowerInclusive = true;
- }
- return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, upperInclusive);
- }
-
- public static PDataType fromLiteral(Object value) {
- if (value == null) {
- return null;
- }
- for (PDataType type : PDataType.values()) {
- if (type.isArrayType()) {
- PhoenixArray arr = (PhoenixArray) value;
- if ((type.getSqlType() == arr.baseType.sqlType + PDataType.ARRAY_TYPE_BASE)
- && type.getJavaClass().isInstance(value)) {
- return type;
+ if (lowerRange != KeyRange.UNBOUND && !lowerInclusive && isFixedWidth()) {
+ lowerRange = ByteUtil.nextKey(lowerRange);
+ lowerInclusive = true;
}
- } else {
- if (type.getJavaClass().isInstance(value)) {
- return type;
+ return KeyRange.getKeyRange(lowerRange, lowerInclusive, upperRange, upperInclusive);
+ }
+
+ public static PDataType fromLiteral(Object value) {
+ if (value == null) { return null; }
+ for (PDataType type : PDataType.values()) {
+ if (type.isArrayType()) {
+ PhoenixArray arr = (PhoenixArray)value;
+ if ((type.getSqlType() == arr.baseType.sqlType + PDataType.ARRAY_TYPE_BASE)
+ && type.getJavaClass().isInstance(value)) { return type; }
+ } else {
+ if (type.getJavaClass().isInstance(value)) { return type; }
+ }
}
- }
+ throw new UnsupportedOperationException("Unsupported literal value [" + value + "] of type "
+ + value.getClass().getName());
}
- throw new UnsupportedOperationException(
- "Unsupported literal value [" + value + "] of type " + value.getClass().getName());
- }
- public int getNanos(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- throw new UnsupportedOperationException("Operation not supported for type " + this);
- }
+ public int getNanos(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ throw new UnsupportedOperationException("Operation not supported for type " + this);
+ }
- public long getMillis(ImmutableBytesWritable ptr, SortOrder sortOrder) {
- throw new UnsupportedOperationException("Operation not supported for type " + this);
- }
+ public long getMillis(ImmutableBytesWritable ptr, SortOrder sortOrder) {
+ throw new UnsupportedOperationException("Operation not supported for type " + this);
+ }
- public Object pad(Object object, Integer maxLength) {
- return object;
- }
+ public Object pad(Object object, Integer maxLength) {
+ return object;
+ }
- public void pad(ImmutableBytesWritable ptr, Integer maxLength, SortOrder sortOrder) {
- }
+ public void pad(ImmutableBytesWritable ptr, Integer maxLength, SortOrder sortOrder) {}
- public static PDataType arrayBaseType(PDataType arrayType) {
- Preconditions.checkArgument(arrayType.isArrayType(), "Not a phoenix array type");
- return fromTypeId(arrayType.getSqlType() - ARRAY_TYPE_BASE);
- }
+ public static PDataType arrayBaseType(PDataType arrayType) {
+ Preconditions.checkArgument(arrayType.isArrayType(), "Not a phoenix array type");
+ return fromTypeId(arrayType.getSqlType() - ARRAY_TYPE_BASE);
+ }
}
[08/50] [abbrv] phoenix git commit: PHOENIX-2025 Phoenix-core's
hbase-default.xml prevents HBaseTestingUtility from starting up in client
apps (Mujtaba Chohan)
Posted by ma...@apache.org.
PHOENIX-2025 Phoenix-core's hbase-default.xml prevents HBaseTestingUtility from starting up in client apps (Mujtaba Chohan)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/dee7a02f
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/dee7a02f
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/dee7a02f
Branch: refs/heads/calcite
Commit: dee7a02f92ec3928a76c0d7536bd69f65fb1d4ef
Parents: d0c8f9d
Author: Thomas D'Silva <td...@salesforce.com>
Authored: Tue Jul 7 13:40:18 2015 -0700
Committer: Thomas D'Silva <td...@salesforce.com>
Committed: Tue Jul 7 13:40:18 2015 -0700
----------------------------------------------------------------------
.../apache/phoenix/mapreduce/util/ConnectionUtil.java | 9 +++++----
.../mapreduce/util/PhoenixConfigurationUtil.java | 12 ++++++++++++
2 files changed, 17 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/dee7a02f/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java
index 294d4e9..000ce59 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java
@@ -54,7 +54,7 @@ public class ConnectionUtil {
*/
public static Connection getInputConnection(final Configuration conf , final Properties props) throws SQLException {
Preconditions.checkNotNull(conf);
- return getConnection(PhoenixConfigurationUtil.getInputCluster(conf),
+ return getConnection(PhoenixConfigurationUtil.getInputCluster(conf), PhoenixConfigurationUtil.getClientPort(conf),
PropertiesUtil.extractProperties(props, conf));
}
@@ -77,7 +77,7 @@ public class ConnectionUtil {
*/
public static Connection getOutputConnection(final Configuration conf, Properties props) throws SQLException {
Preconditions.checkNotNull(conf);
- return getConnection(PhoenixConfigurationUtil.getOutputCluster(conf),
+ return getConnection(PhoenixConfigurationUtil.getOutputCluster(conf), PhoenixConfigurationUtil.getClientPort(conf),
PropertiesUtil.extractProperties(props, conf));
}
@@ -85,11 +85,12 @@ public class ConnectionUtil {
* Returns the {@link Connection} from a ZooKeeper cluster string.
*
* @param quorum a ZooKeeper quorum connection string
+ * @param clientPort a ZooKeeper client port
* @return a Phoenix connection to the given connection string
*/
- private static Connection getConnection(final String quorum, Properties props) throws SQLException {
+ private static Connection getConnection(final String quorum, final int clientPort, Properties props) throws SQLException {
Preconditions.checkNotNull(quorum);
- return DriverManager.getConnection(QueryUtil.getUrl(quorum), props);
+ return DriverManager.getConnection(QueryUtil.getUrl(quorum, clientPort), props);
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/dee7a02f/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
index 6e0e5e4..bba96ac 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
@@ -94,6 +94,8 @@ public final class PhoenixConfigurationUtil {
public static final String MAPREDUCE_INPUT_CLUSTER_QUORUM = "phoenix.mapreduce.input.cluster.quorum";
public static final String MAPREDUCE_OUTPUT_CLUSTER_QUORUM = "phoneix.mapreduce.output.cluster.quorum";
+
+ public static final String HBASE_ZOOKEEPER_CLIENT_PORT = "hbase.zookeeper.property.clientPort";
public enum SchemaType {
TABLE,
@@ -363,6 +365,16 @@ public final class PhoenixConfigurationUtil {
}
return quorum;
}
+
+ /**
+ * Returns the HBase Client Port
+ * @param configuration
+ * @return
+ */
+ public static int getClientPort(final Configuration configuration) {
+ Preconditions.checkNotNull(configuration);
+ return Integer.parseInt(configuration.get(HBASE_ZOOKEEPER_CLIENT_PORT));
+ }
public static void loadHBaseConfiguration(Job job) throws IOException {
// load hbase-site.xml
[25/50] [abbrv] phoenix git commit: PHOENIX-2112 Phoenix-Spark need
to support UTF8String for spark 1.4.0 (Yi Tian)
Posted by ma...@apache.org.
PHOENIX-2112 Phoenix-Spark need to support UTF8String for spark 1.4.0 (Yi Tian)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/70c542d8
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/70c542d8
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/70c542d8
Branch: refs/heads/calcite
Commit: 70c542d8e7b8bdcea58e2ef8cbf76143ec5ae66c
Parents: 052836c
Author: Josh Mahonin <jm...@interset.com>
Authored: Mon Jul 13 16:15:42 2015 -0400
Committer: Josh Mahonin <jm...@interset.com>
Committed: Mon Jul 13 16:15:42 2015 -0400
----------------------------------------------------------------------
phoenix-spark/pom.xml | 2 +-
.../main/scala/org/apache/phoenix/spark/PhoenixRelation.scala | 7 ++++---
2 files changed, 5 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/70c542d8/phoenix-spark/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-spark/pom.xml b/phoenix-spark/pom.xml
index 289801a..ef4d2c4 100644
--- a/phoenix-spark/pom.xml
+++ b/phoenix-spark/pom.xml
@@ -34,7 +34,7 @@
<name>Phoenix - Spark</name>
<properties>
- <spark.version>1.3.0</spark.version>
+ <spark.version>1.4.0</spark.version>
<scala.version>2.10.4</scala.version>
<scala.binary.version>2.10</scala.binary.version>
<top.dir>${project.basedir}/..</top.dir>
http://git-wip-us.apache.org/repos/asf/phoenix/blob/70c542d8/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRelation.scala
----------------------------------------------------------------------
diff --git a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRelation.scala b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRelation.scala
index 8804f3b..f20ad61 100644
--- a/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRelation.scala
+++ b/phoenix-spark/src/main/scala/org/apache/phoenix/spark/PhoenixRelation.scala
@@ -19,10 +19,10 @@ package org.apache.phoenix.spark
import org.apache.hadoop.conf.Configuration
import org.apache.spark.rdd.RDD
-import org.apache.spark.sql.types.StructType
+import org.apache.spark.sql.types.{UTF8String, StructType}
import org.apache.spark.sql.{Row, SQLContext}
import org.apache.spark.sql.sources._
-import org.apache.commons.lang.StringEscapeUtils.escapeSql
+import org.apache.phoenix.util.StringUtil.escapeStringConstant
case class PhoenixRelation(tableName: String, zkUrl: String)(@transient val sqlContext: SQLContext)
extends BaseRelation with PrunedFilteredScan {
@@ -91,7 +91,8 @@ case class PhoenixRelation(tableName: String, zkUrl: String)(@transient val sqlC
// Helper function to escape string values in SQL queries
private def compileValue(value: Any): Any = value match {
- case stringValue: String => s"'${escapeSql(stringValue)}'"
+ case stringValue: String => s"'${escapeStringConstant(stringValue)}'"
+ case stringValue: UTF8String => s"'${escapeStringConstant(stringValue.toString)}'"
case _ => value
}
}
[23/50] [abbrv] phoenix git commit: PHOENIX-2098 Pig Udf that given a
count Reserve chunks of numbers for a sequence (Siddhi Mehta)
Posted by ma...@apache.org.
PHOENIX-2098 Pig Udf that given a count Reserve chunks of numbers for a sequence (Siddhi Mehta)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/300de02c
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/300de02c
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/300de02c
Branch: refs/heads/calcite
Commit: 300de02c01def7e8f23dfc1930b2d9d281c1bebd
Parents: 81b3cb3
Author: James Taylor <jt...@salesforce.com>
Authored: Fri Jul 10 16:32:56 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Fri Jul 10 16:32:56 2015 -0700
----------------------------------------------------------------------
.../phoenix/pig/udf/ReserveNSequenceTestIT.java | 262 +++++++++++++++++++
.../phoenix/pig/udf/ReserveNSequence.java | 88 +++++++
2 files changed, 350 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/300de02c/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java b/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java
new file mode 100644
index 0000000..2cbb6cc
--- /dev/null
+++ b/phoenix-pig/src/it/java/org/apache/phoenix/pig/udf/ReserveNSequenceTestIT.java
@@ -0,0 +1,262 @@
+/**
+ *
+ */
+package org.apache.phoenix.pig.udf;
+
+import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR;
+import static org.apache.phoenix.util.TestUtil.LOCALHOST;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.phoenix.end2end.BaseHBaseManagedTimeIT;
+import org.apache.pig.data.Tuple;
+import org.apache.pig.data.TupleFactory;
+import org.apache.pig.impl.util.UDFContext;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Test class to run all the Pig Sequence UDF integration tests against a virtual map reduce cluster.
+ */
+public class ReserveNSequenceTestIT extends BaseHBaseManagedTimeIT {
+
+ private static final String CREATE_SEQUENCE_SYNTAX = "CREATE SEQUENCE %s START WITH %s INCREMENT BY %s MINVALUE %s MAXVALUE %s CACHE %s";
+ private static final String SEQUENCE_NAME = "my_schema.my_sequence";
+ private static final long MAX_VALUE = 10;
+
+ private static TupleFactory TF;
+ private static Connection conn;
+ private static String zkQuorum;
+ private static Configuration conf;
+ private static UDFContext udfContext;
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ conf = getTestClusterConfig();
+ zkQuorum = LOCALHOST + JDBC_PROTOCOL_SEPARATOR + getZKClientPort(getTestClusterConfig());
+ conf.set(HConstants.ZOOKEEPER_QUORUM, zkQuorum);
+ // Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl());
+ // Pig variables
+ TF = TupleFactory.getInstance();
+ }
+
+ @Before
+ public void setUp() throws SQLException {
+ createSequence();
+ createUdfContext();
+ }
+
+ @Test
+ public void testReserve() throws Exception {
+ doTest(new UDFTestProperties(1));
+ }
+
+ @Test
+ public void testReserveN() throws Exception {
+ doTest(new UDFTestProperties(5));
+ }
+
+ @Test
+ public void testReserveNwithPreviousAllocations() throws Exception {
+ UDFTestProperties props = new UDFTestProperties(5);
+ props.setCurrentValue(4);
+ doTest(props);
+ }
+
+ @Test
+ public void testReserveWithZero() throws Exception {
+ UDFTestProperties props = new UDFTestProperties(0);
+ props.setExceptionExpected(true);
+ props.setExceptionClass(IllegalArgumentException.class);
+ props.setErrorMessage(ReserveNSequence.INVALID_NUMBER_MESSAGE);
+ doTest(props);
+ }
+
+ @Test
+ public void testReserveWithNegativeNumber() throws Exception {
+ UDFTestProperties props = new UDFTestProperties(-1);
+ props.setExceptionExpected(true);
+ props.setExceptionClass(IllegalArgumentException.class);
+ props.setErrorMessage(ReserveNSequence.INVALID_NUMBER_MESSAGE);
+ doTest(props);
+ }
+
+ @Test
+ public void testReserveMaxLimit() throws Exception {
+ UDFTestProperties props = new UDFTestProperties(MAX_VALUE);
+ props.setExceptionExpected(true);
+ props.setExceptionClass(IOException.class);
+ props.setErrorMessage("Reached MAXVALUE of sequence");
+ doTest(props);
+ }
+
+ @Test
+ public void testNoSequenceName() throws Exception {
+ UDFTestProperties props = new UDFTestProperties(1);
+ props.setExceptionExpected(true);
+ props.setSequenceName(null);
+ props.setExceptionClass(NullPointerException.class);
+ props.setErrorMessage(ReserveNSequence.EMPTY_SEQUENCE_NAME_MESSAGE);
+ doTest(props);
+ }
+
+ @Test
+ public void testSequenceNotExisting() throws Exception {
+ UDFTestProperties props = new UDFTestProperties(1);
+ props.setExceptionExpected(true);
+ props.setSequenceName("foo.bar");
+ props.setExceptionClass(IOException.class);
+ props.setErrorMessage("Sequence undefined");
+ doTest(props);
+ }
+
+ private void doTest(UDFTestProperties props) throws Exception {
+ setCurrentValue(props.getCurrentValue());
+ Tuple tuple = TF.newTuple(3);
+ tuple.set(0, props.getNumToReserve());
+ tuple.set(1, props.getSequenceName());
+ tuple.set(2, zkQuorum);
+ Long result = null;
+ try {
+ ReserveNSequence udf = new ReserveNSequence();
+ result = udf.exec(tuple);
+ validateReservedSequence(props.getCurrentValue(), props.getNumToReserve(), result);
+ } catch (Exception e) {
+ if (props.isExceptionExpected()) {
+ assertEquals(props.getExceptionClass(), e.getClass());
+ e.getMessage().contains(props.getErrorMessage());
+ } else {
+ throw e;
+ }
+ }
+
+ }
+
+ private void createUdfContext() {
+ conf.set(ReserveNSequence.SEQUENCE_NAME_CONF_KEY, SEQUENCE_NAME);
+ udfContext = UDFContext.getUDFContext();
+ udfContext.addJobConf(conf);
+ }
+
+ private void validateReservedSequence(Long currentValue, long count, Long result) throws SQLException {
+ Long startIndex = currentValue + 1;
+ assertEquals("Start index is incorrect", startIndex, result);
+ final long newNextSequenceValue = getNextSequenceValue();
+ assertEquals(startIndex + count, newNextSequenceValue);
+ }
+
+ private void createSequence() throws SQLException {
+ conn.createStatement().execute(String.format(CREATE_SEQUENCE_SYNTAX, SEQUENCE_NAME, 1, 1, 1, MAX_VALUE, 1));
+ conn.commit();
+ }
+
+ private void setCurrentValue(long currentValue) throws SQLException {
+ for (int i = 1; i <= currentValue; i++) {
+ getNextSequenceValue();
+ }
+ }
+
+ private long getNextSequenceValue() throws SQLException {
+ String ddl = new StringBuilder().append("SELECT NEXT VALUE FOR ").append(SEQUENCE_NAME).toString();
+ ResultSet rs = conn.createStatement().executeQuery(ddl);
+ assertTrue(rs.next());
+ conn.commit();
+ return rs.getLong(1);
+ }
+
+ private void dropSequence() throws Exception {
+ String ddl = new StringBuilder().append("DROP SEQUENCE ").append(SEQUENCE_NAME).toString();
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ udfContext.reset();
+ dropSequence();
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ conn.close();
+ }
+
+ /**
+ * Static class to define properties for the test
+ */
+ private static class UDFTestProperties {
+ private final Long numToReserve;
+ private Long currentValue = 1L;
+ private String sequenceName = SEQUENCE_NAME;
+ private boolean exceptionExpected = false;
+ private Class exceptionClass = null;
+ private String errorMessage = null;
+
+ public UDFTestProperties(long numToReserve) {
+ this.numToReserve = numToReserve;
+ }
+
+ public Long getCurrentValue() {
+ return currentValue;
+ }
+
+ public void setCurrentValue(long currentValue) {
+ this.currentValue = currentValue;
+ }
+
+ public String getSequenceName() {
+ return sequenceName;
+ }
+
+ public void setSequenceName(String sequenceName) {
+ this.sequenceName = sequenceName;
+ }
+
+ public boolean isExceptionExpected() {
+ return exceptionExpected;
+ }
+
+ public void setExceptionExpected(boolean shouldThrowException) {
+ this.exceptionExpected = shouldThrowException;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public Long getNumToReserve() {
+ return numToReserve;
+ }
+
+ public Class getExceptionClass() {
+ return exceptionClass;
+ }
+
+ public void setExceptionClass(Class exceptionClass) {
+ this.exceptionClass = exceptionClass;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/300de02c/phoenix-pig/src/main/java/org/apache/phoenix/pig/udf/ReserveNSequence.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/main/java/org/apache/phoenix/pig/udf/ReserveNSequence.java b/phoenix-pig/src/main/java/org/apache/phoenix/pig/udf/ReserveNSequence.java
new file mode 100644
index 0000000..308f170
--- /dev/null
+++ b/phoenix-pig/src/main/java/org/apache/phoenix/pig/udf/ReserveNSequence.java
@@ -0,0 +1,88 @@
+/**
+ *
+ */
+package org.apache.phoenix.pig.udf;
+
+/*
+ * 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.
+ */
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.phoenix.mapreduce.util.ConnectionUtil;
+import org.apache.pig.EvalFunc;
+import org.apache.pig.data.Tuple;
+import org.apache.pig.impl.util.UDFContext;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * UDF to Reserve a chunk of numbers for a given sequence
+ *
+ * @note The way this UDF is invoked we open a new connection for every tuple row. The UDF will not perform well on
+ * large datasets as it involves creating a new connection for every tuple row
+ */
+public class ReserveNSequence extends EvalFunc<Long> {
+
+ public static final String INVALID_TUPLE_MESSAGE = "Tuple should have correct fields(NumtoReserve,SequenceName,zkquorum.";
+ public static final String EMPTY_SEQUENCE_NAME_MESSAGE = "Sequence name should be not null";
+ public static final String EMPTY_ZK_MESSAGE = "ZKQuorum should be not null";
+ public static final String INVALID_NUMBER_MESSAGE = "Number of Sequences to Reserve should be greater than 0";
+ public static final String SEQUENCE_NAME_CONF_KEY = "phoenix.sequence.name";
+
+ /**
+ * Reserve N next sequences for a sequence name. N is the first field in the tuple. Sequence name is the second
+ * field in the tuple zkquorum is the third field in the tuple
+ */
+ @Override
+ public Long exec(Tuple input) throws IOException {
+ Preconditions.checkArgument(input != null && input.size() == 3, INVALID_TUPLE_MESSAGE);
+ Long numToReserve = (Long)(input.get(0));
+ Preconditions.checkArgument(numToReserve > 0, INVALID_NUMBER_MESSAGE);
+ String sequenceName = (String)input.get(1);
+ Preconditions.checkNotNull(sequenceName, EMPTY_SEQUENCE_NAME_MESSAGE);
+ String zkquorum = (String)input.get(2);
+ Preconditions.checkNotNull(zkquorum, EMPTY_ZK_MESSAGE);
+ UDFContext context = UDFContext.getUDFContext();
+ Configuration configuration = context.getJobConf();
+ configuration.set(HConstants.ZOOKEEPER_QUORUM, zkquorum);
+ Connection connection = null;
+ ResultSet rs = null;
+ try {
+ connection = ConnectionUtil.getOutputConnection(configuration);
+ String sql = getNextNSequenceSelectStatement(Long.valueOf(numToReserve), sequenceName);
+ rs = connection.createStatement().executeQuery(sql);
+ Preconditions.checkArgument(rs.next());
+ Long startIndex = rs.getLong(1);
+ rs.close();
+ connection.commit();
+ return startIndex;
+ } catch (SQLException e) {
+ throw new IOException("Caught exception while processing row." + e.getMessage(), e);
+ } finally {
+ try {
+ if (connection != null) {
+ connection.close();
+ }
+ } catch (SQLException e) {
+ throw new IOException("Caught exception while closing connection", e);
+ }
+ }
+ }
+
+ private String getNextNSequenceSelectStatement(Long numToReserve, String sequenceName) {
+ return new StringBuilder().append("SELECT NEXT " + numToReserve + " VALUES" + " FOR ").append(sequenceName)
+ .toString();
+ }
+
+}
[49/50] [abbrv] phoenix git commit: Merge branch 'master' into calcite
Posted by ma...@apache.org.
Merge branch 'master' into calcite
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/597e0013
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/597e0013
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/597e0013
Branch: refs/heads/calcite
Commit: 597e0013cee4285704aecc5c36d6727262ca9885
Parents: 0641043 b38a624
Author: maryannxue <we...@intel.com>
Authored: Mon Jul 20 12:32:48 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Mon Jul 20 12:32:48 2015 -0400
----------------------------------------------------------------------
dev/eclipse_prefs_phoenix.epf | 2 +-
.../apache/phoenix/end2end/AlterTableIT.java | 449 +++-
.../org/apache/phoenix/end2end/ArrayIT.java | 178 ++
.../end2end/ArrayToStringFunctionIT.java | 654 ++++++
.../org/apache/phoenix/end2end/IsNullIT.java | 52 +-
.../apache/phoenix/end2end/LpadFunctionIT.java | 24 +
.../apache/phoenix/end2end/MD5FunctionIT.java | 19 +
.../apache/phoenix/end2end/ReverseScanIT.java | 59 +-
.../phoenix/end2end/RowValueConstructorIT.java | 103 +-
.../end2end/SequenceBulkAllocationIT.java | 1286 +++++++++++
.../org/apache/phoenix/end2end/SequenceIT.java | 27 +
.../apache/phoenix/end2end/SortOrderFIT.java | 563 -----
.../org/apache/phoenix/end2end/SortOrderIT.java | 572 +++++
.../phoenix/end2end/UserDefinedFunctionsIT.java | 212 +-
.../java/org/apache/phoenix/end2end/ViewIT.java | 23 +
.../iterate/RoundRobinResultIteratorIT.java | 80 +
phoenix-core/src/main/antlr3/PhoenixSQL.g | 35 +-
.../phoenix/compile/CreateFunctionCompiler.java | 4 +-
.../apache/phoenix/compile/FromCompiler.java | 21 +-
.../apache/phoenix/compile/JoinCompiler.java | 8 +-
.../phoenix/compile/ListJarsQueryPlan.java | 216 ++
.../apache/phoenix/compile/OrderByCompiler.java | 4 +-
.../phoenix/compile/OrderPreservingTracker.java | 7 +-
.../phoenix/compile/ProjectionCompiler.java | 2 +-
.../apache/phoenix/compile/QueryCompiler.java | 9 +-
.../org/apache/phoenix/compile/ScanRanges.java | 5 +-
.../apache/phoenix/compile/SequenceManager.java | 70 +-
.../compile/SequenceValueExpression.java | 14 +-
.../compile/TupleProjectionCompiler.java | 5 +-
.../apache/phoenix/compile/UnionCompiler.java | 5 +-
.../apache/phoenix/compile/UpsertCompiler.java | 16 +-
.../apache/phoenix/compile/WhereOptimizer.java | 53 +-
.../coprocessor/BaseScannerRegionObserver.java | 2 +
.../coprocessor/MetaDataEndpointImpl.java | 457 +++-
.../phoenix/coprocessor/MetaDataProtocol.java | 2 +-
.../coprocessor/SequenceRegionObserver.java | 64 +-
.../UngroupedAggregateRegionObserver.java | 108 +-
.../coprocessor/generated/MetaDataProtos.java | 1243 ++++++++++-
.../coprocessor/generated/PFunctionProtos.java | 100 +-
.../coprocessor/generated/PTableProtos.java | 105 +-
.../phoenix/exception/SQLExceptionCode.java | 4 +
.../apache/phoenix/execute/BaseQueryPlan.java | 23 +-
.../DescVarLengthFastByteComparisons.java | 219 ++
.../phoenix/execute/EmptyTableQueryPlan.java | 96 +
.../org/apache/phoenix/execute/ScanPlan.java | 14 +-
.../expression/ArrayConstructorExpression.java | 21 +-
.../phoenix/expression/ExpressionType.java | 4 +-
.../phoenix/expression/OrderByExpression.java | 13 +-
.../RowValueConstructorExpression.java | 8 +-
.../aggregator/ServerAggregators.java | 1 +
.../function/ArrayConcatFunction.java | 11 +-
.../function/ArrayModifierFunction.java | 3 +-
.../function/ArrayToStringFunction.java | 84 +
.../expression/function/LpadFunction.java | 8 +-
.../expression/util/regex/JONIPattern.java | 5 +-
.../apache/phoenix/filter/SkipScanFilter.java | 3 +-
.../apache/phoenix/index/IndexMaintainer.java | 127 +-
.../phoenix/iterate/BaseResultIterators.java | 109 +-
.../phoenix/iterate/OrderedResultIterator.java | 52 +-
.../iterate/RoundRobinResultIterator.java | 2 +-
.../apache/phoenix/jdbc/PhoenixConnection.java | 29 +-
.../apache/phoenix/jdbc/PhoenixStatement.java | 213 +-
.../phoenix/mapreduce/util/ConnectionUtil.java | 9 +-
.../util/PhoenixConfigurationUtil.java | 14 +
.../phoenix/monitoring/MetricsStopWatch.java | 8 +-
.../apache/phoenix/parse/AddJarsStatement.java | 38 +
.../org/apache/phoenix/parse/CastParseNode.java | 2 +-
.../phoenix/parse/CreateFunctionStatement.java | 7 +-
.../phoenix/parse/DeleteJarStatement.java | 19 +
.../apache/phoenix/parse/ListJarsStatement.java | 34 +
.../org/apache/phoenix/parse/PFunction.java | 28 +-
.../apache/phoenix/parse/ParseNodeFactory.java | 22 +-
.../apache/phoenix/parse/SelectStatement.java | 6 +-
.../phoenix/parse/SequenceValueParseNode.java | 8 +-
.../phoenix/query/ConnectionQueryServices.java | 5 +-
.../query/ConnectionQueryServicesImpl.java | 128 +-
.../query/ConnectionlessQueryServicesImpl.java | 20 +-
.../query/DelegateConnectionQueryServices.java | 13 +-
.../java/org/apache/phoenix/query/KeyRange.java | 27 +-
.../apache/phoenix/query/QueryConstants.java | 3 +
.../phoenix/query/QueryServicesOptions.java | 2 +-
.../apache/phoenix/schema/DelegateTable.java | 5 +
.../apache/phoenix/schema/MetaDataClient.java | 99 +-
.../java/org/apache/phoenix/schema/PTable.java | 9 +
.../org/apache/phoenix/schema/PTableImpl.java | 79 +-
.../org/apache/phoenix/schema/RowKeySchema.java | 44 +-
.../phoenix/schema/RowKeyValueAccessor.java | 12 +-
.../org/apache/phoenix/schema/Sequence.java | 107 +-
.../phoenix/schema/SequenceAllocation.java | 48 +
.../org/apache/phoenix/schema/TableRef.java | 2 +
.../org/apache/phoenix/schema/ValueSchema.java | 30 +-
.../phoenix/schema/stats/StatisticsUtil.java | 4 +-
.../phoenix/schema/types/PArrayDataType.java | 726 ++++---
.../phoenix/schema/types/PBinaryArray.java | 122 +-
.../phoenix/schema/types/PBooleanArray.java | 112 +-
.../apache/phoenix/schema/types/PCharArray.java | 128 +-
.../apache/phoenix/schema/types/PDataType.java | 2037 +++++++++---------
.../apache/phoenix/schema/types/PDateArray.java | 131 +-
.../phoenix/schema/types/PDecimalArray.java | 126 +-
.../phoenix/schema/types/PDoubleArray.java | 128 +-
.../phoenix/schema/types/PFloatArray.java | 130 +-
.../phoenix/schema/types/PIntegerArray.java | 130 +-
.../apache/phoenix/schema/types/PLongArray.java | 130 +-
.../phoenix/schema/types/PSmallintArray.java | 130 +-
.../apache/phoenix/schema/types/PTimeArray.java | 133 +-
.../phoenix/schema/types/PTimestampArray.java | 132 +-
.../phoenix/schema/types/PTinyintArray.java | 130 +-
.../schema/types/PUnsignedDateArray.java | 128 +-
.../schema/types/PUnsignedDoubleArray.java | 136 +-
.../schema/types/PUnsignedFloatArray.java | 130 +-
.../phoenix/schema/types/PUnsignedIntArray.java | 130 +-
.../schema/types/PUnsignedLongArray.java | 130 +-
.../schema/types/PUnsignedSmallintArray.java | 132 +-
.../schema/types/PUnsignedTimeArray.java | 132 +-
.../schema/types/PUnsignedTimestampArray.java | 134 +-
.../schema/types/PUnsignedTinyintArray.java | 132 +-
.../phoenix/schema/types/PVarbinaryArray.java | 130 +-
.../phoenix/schema/types/PVarcharArray.java | 130 +-
.../java/org/apache/phoenix/util/ByteUtil.java | 12 +-
.../org/apache/phoenix/util/MetaDataUtil.java | 16 +-
.../org/apache/phoenix/util/PhoenixRuntime.java | 153 +-
.../apache/phoenix/util/PhoenixStopWatch.java | 81 +
.../java/org/apache/phoenix/util/QueryUtil.java | 4 +-
.../java/org/apache/phoenix/util/ScanUtil.java | 24 +-
.../org/apache/phoenix/util/SchemaUtil.java | 41 +-
.../org/apache/phoenix/util/SequenceUtil.java | 47 +-
.../java/org/apache/phoenix/util/TupleUtil.java | 7 +-
.../org/apache/phoenix/util/UpgradeUtil.java | 730 +++++--
.../phoenix/compile/QueryCompilerTest.java | 156 +-
.../expression/ArrayAppendFunctionTest.java | 76 +-
.../expression/ArrayConcatFunctionTest.java | 129 ++
.../expression/ArrayPrependFunctionTest.java | 61 +
.../expression/ArrayToStringFunctionTest.java | 376 ++++
.../util/PhoenixConfigurationUtilTest.java | 28 +-
.../apache/phoenix/parse/CastParseNodeTest.java | 57 +
.../apache/phoenix/parse/QueryParserTest.java | 19 +-
.../org/apache/phoenix/query/OrderByTest.java | 84 +
.../phoenix/schema/SequenceAllocationTest.java | 59 +
.../schema/types/PDataTypeForArraysTest.java | 70 +-
.../phoenix/schema/types/PDataTypeTest.java | 12 +
.../org/apache/phoenix/util/QueryUtilTest.java | 36 +-
.../apache/phoenix/util/SequenceUtilTest.java | 54 +
phoenix-pherf/config/log4j.properties | 58 +
phoenix-pherf/pom.xml | 2 +-
.../org/apache/phoenix/pherf/DataIngestIT.java | 8 +
.../test/resources/datamodel/test_schema.sql | 2 +-
.../phoenix/pig/PhoenixHBaseLoaderIT.java | 141 +-
.../phoenix/pig/PhoenixHBaseStorerIT.java | 4 +-
.../phoenix/pig/udf/ReserveNSequenceTestIT.java | 262 +++
.../apache/phoenix/pig/PhoenixHBaseStorage.java | 51 +-
.../phoenix/pig/udf/ReserveNSequence.java | 88 +
phoenix-protocol/src/main/MetaDataService.proto | 14 +-
phoenix-protocol/src/main/PFunction.proto | 1 +
phoenix-protocol/src/main/PTable.proto | 2 +
phoenix-spark/pom.xml | 2 +-
phoenix-spark/src/it/resources/setup.sql | 4 +-
.../apache/phoenix/spark/PhoenixSparkIT.scala | 58 +-
.../org/apache/phoenix/spark/PhoenixRDD.scala | 24 +-
.../apache/phoenix/spark/PhoenixRelation.scala | 7 +-
159 files changed, 12789 insertions(+), 4879 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/597e0013/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/597e0013/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
----------------------------------------------------------------------
[32/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
index 4e32cc0..dd11569 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
@@ -20,6 +20,7 @@ package org.apache.phoenix.schema.types;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.sql.Types;
import java.text.Format;
import java.util.LinkedList;
import java.util.List;
@@ -34,61 +35,88 @@ import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.ValueSchema;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.SchemaUtil;
import org.apache.phoenix.util.TrustedByteArrayOutputStream;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
/**
- * The datatype for PColummns that are Arrays. Any variable length array would follow the below order.
- * Every element would be seperated by a seperator byte '0'. Null elements are counted and once a first
- * non null element appears we write the count of the nulls prefixed with a seperator byte.
- * Trailing nulls are not taken into account. The last non null element is followed by two seperator bytes.
- * For eg a, b, null, null, c, null -> 65 0 66 0 0 2 67 0 0 0
- * a null null null b c null d -> 65 0 0 3 66 0 67 0 0 1 68 0 0 0.
- * The reason we use this serialization format is to allow the
- * byte array of arrays of the same type to be directly comparable against each other.
- * This prevents a costly deserialization on compare and allows an array column to be used as the last column in a primary key constraint.
+ * The datatype for PColummns that are Arrays. Any variable length array would follow the below order. Every element
+ * would be seperated by a seperator byte '0'. Null elements are counted and once a first non null element appears we
+ * write the count of the nulls prefixed with a seperator byte. Trailing nulls are not taken into account. The last non
+ * null element is followed by two seperator bytes. For eg a, b, null, null, c, null -> 65 0 66 0 0 2 67 0 0 0 a null
+ * null null b c null d -> 65 0 0 3 66 0 67 0 0 1 68 0 0 0. The reason we use this serialization format is to allow the
+ * byte array of arrays of the same type to be directly comparable against each other. This prevents a costly
+ * deserialization on compare and allows an array column to be used as the last column in a primary key constraint.
*/
public abstract class PArrayDataType<T> extends PDataType<T> {
+ @Override
+ public final int getResultSetSqlType() {
+ return Types.ARRAY;
+ }
+
+ @Override
+ public final void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
+ Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
+ Integer desiredScale, SortOrder desiredModifier, boolean expectedRowKeyOrderOptimizable) {
+ coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
+ this, actualModifer, desiredModifier, expectedRowKeyOrderOptimizable);
+ }
+
+ @Override
+ public final void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
+ Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
+ Integer desiredScale, SortOrder desiredModifier) {
+ coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
+ this, actualModifer, desiredModifier, true);
+ }
+
public static final byte ARRAY_SERIALIZATION_VERSION = 1;
- protected PArrayDataType(String sqlTypeName, int sqlType, Class clazz, PDataCodec codec, int ordinal) {
- super(sqlTypeName, sqlType, clazz, codec, ordinal);
- }
+ protected PArrayDataType(String sqlTypeName, int sqlType, Class clazz, PDataCodec codec, int ordinal) {
+ super(sqlTypeName, sqlType, clazz, codec, ordinal);
+ }
+
+ private static byte getSeparatorByte(boolean rowKeyOrderOptimizable, SortOrder sortOrder) {
+ return SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable, false, sortOrder);
+ }
- public byte[] toBytes(Object object, PDataType baseType, SortOrder sortOrder) {
- if(object == null) {
- throw new ConstraintViolationException(this + " may not be null");
- }
- PhoenixArray arr = ((PhoenixArray)object);
+ public byte[] toBytes(Object object, PDataType baseType, SortOrder sortOrder) {
+ return toBytes(object, baseType, sortOrder, true);
+ }
+
+ public byte[] toBytes(Object object, PDataType baseType, SortOrder sortOrder, boolean rowKeyOrderOptimizable) {
+ if (object == null) { throw new ConstraintViolationException(this + " may not be null"); }
+ PhoenixArray arr = ((PhoenixArray)object);
int noOfElements = arr.numElements;
- if(noOfElements == 0) {
- return ByteUtil.EMPTY_BYTE_ARRAY;
- }
+ if (noOfElements == 0) { return ByteUtil.EMPTY_BYTE_ARRAY; }
TrustedByteArrayOutputStream byteStream = null;
- if (!baseType.isFixedWidth()) {
- Pair<Integer, Integer> nullsVsNullRepeationCounter = new Pair<>();
- int size = estimateByteSize(object, nullsVsNullRepeationCounter,
- PDataType.fromTypeId((baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE)));
- size += ((2 * Bytes.SIZEOF_BYTE) + (noOfElements - nullsVsNullRepeationCounter.getFirst()) * Bytes.SIZEOF_BYTE)
- + (nullsVsNullRepeationCounter.getSecond() * 2 * Bytes.SIZEOF_BYTE);
- // Assume an offset array that fit into Short.MAX_VALUE. Also not considering nulls that could be > 255
- // In both of these cases, finally an array copy would happen
- int capacity = noOfElements * Bytes.SIZEOF_SHORT;
- // Here the int for noofelements, byte for the version, int for the offsetarray position and 2 bytes for the end seperator
- byteStream = new TrustedByteArrayOutputStream(size + capacity + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE + Bytes.SIZEOF_INT);
- } else {
- int size = arr.getMaxLength() * noOfElements;
- // Here the int for noofelements, byte for the version
- byteStream = new TrustedByteArrayOutputStream(size);
- }
- DataOutputStream oStream = new DataOutputStream(byteStream);
- // Handles bit inversion also
- return createArrayBytes(byteStream, oStream, (PhoenixArray)object, noOfElements, baseType, sortOrder);
- }
-
+ if (!baseType.isFixedWidth()) {
+ Pair<Integer, Integer> nullsVsNullRepeationCounter = new Pair<>();
+ int size = estimateByteSize(object, nullsVsNullRepeationCounter,
+ PDataType.fromTypeId((baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE)));
+ size += ((2 * Bytes.SIZEOF_BYTE) + (noOfElements - nullsVsNullRepeationCounter.getFirst())
+ * Bytes.SIZEOF_BYTE)
+ + (nullsVsNullRepeationCounter.getSecond() * 2 * Bytes.SIZEOF_BYTE);
+ // Assume an offset array that fit into Short.MAX_VALUE. Also not considering nulls that could be > 255
+ // In both of these cases, finally an array copy would happen
+ int capacity = noOfElements * Bytes.SIZEOF_SHORT;
+ // Here the int for noofelements, byte for the version, int for the offsetarray position and 2 bytes for the
+ // end seperator
+ byteStream = new TrustedByteArrayOutputStream(size + capacity + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE
+ + Bytes.SIZEOF_INT);
+ } else {
+ int size = arr.getMaxLength() * noOfElements;
+ // Here the int for noofelements, byte for the version
+ byteStream = new TrustedByteArrayOutputStream(size);
+ }
+ DataOutputStream oStream = new DataOutputStream(byteStream);
+ // Handles bit inversion also
+ return createArrayBytes(byteStream, oStream, (PhoenixArray)object, noOfElements, baseType, sortOrder, rowKeyOrderOptimizable);
+ }
+
public static int serializeNulls(DataOutputStream oStream, int nulls) throws IOException {
// We need to handle 3 different cases here
// 1) Arrays with repeating nulls in the middle which is less than 255
@@ -97,12 +125,15 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
// Take a case where we have two arrays that has the following elements
// Array 1 - size : 240, elements = abc, bcd, null, null, bcd,null,null......,null, abc
// Array 2 - size : 16 : elements = abc, bcd, null, null, bcd, null, null...null, abc
- // In both case the elements and the value array will be the same but the Array 1 is actually smaller because it has more nulls.
- // Now we should have mechanism to show that we treat arrays with more nulls as lesser. Hence in the above case as
+ // In both case the elements and the value array will be the same but the Array 1 is actually smaller because it
+ // has more nulls.
+ // Now we should have mechanism to show that we treat arrays with more nulls as lesser. Hence in the above case
+ // as
// 240 > Bytes.MAX_VALUE, by always inverting the number of nulls we would get a +ve value
- // For Array 2, by inverting we would get a -ve value. On comparison Array 2 > Array 1.
- // Now for cases where the number of nulls is greater than 255, we would write an those many (byte)1, it is bigger than 255.
- // This would ensure that we don't compare with triple zero which is used as an end byte
+ // For Array 2, by inverting we would get a -ve value. On comparison Array 2 > Array 1.
+ // Now for cases where the number of nulls is greater than 255, we would write an those many (byte)1, it is
+ // bigger than 255.
+ // This would ensure that we don't compare with triple zero which is used as an end byte
if (nulls > 0) {
oStream.write(QueryConstants.SEPARATOR_BYTE);
int nMultiplesOver255 = nulls / 255;
@@ -110,61 +141,65 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
// Don't write a zero byte, as we need to ensure that the only triple zero
// byte occurs at the end of the array (i.e. the terminator byte for the
// element plus the double zero byte at the end of the array).
- oStream.write((byte)1);
+ oStream.write((byte)1);
}
int nRemainingNulls = nulls % 255; // From 0 to 254
// Write a byte for the remaining null elements
if (nRemainingNulls > 0) {
// Remaining null elements is from 1 to 254.
- // Subtract one and invert so that more remaining nulls becomes smaller than less
- // remaining nulls and min byte value is always greater than 1, the repeating value
+ // Subtract one and invert so that more remaining nulls becomes smaller than less
+ // remaining nulls and min byte value is always greater than 1, the repeating value
// used for arrays with more than 255 repeating null elements.
- // The reason we invert is that an array with less null elements has a non
+ // The reason we invert is that an array with less null elements has a non
// null element sooner than an array with more null elements. Thus, the more
// null elements you have, the smaller the array becomes.
- byte nNullByte = SortOrder.invert((byte)(nRemainingNulls-1));
+ byte nNullByte = SortOrder.invert((byte)(nRemainingNulls - 1));
oStream.write(nNullByte); // Single byte for repeating nulls
}
}
return 0;
}
- public static int serializeNulls(byte[] bytes, int position, int nulls){
+ public static int serializeNulls(byte[] bytes, int position, int nulls) {
int nMultiplesOver255 = nulls / 255;
while (nMultiplesOver255-- > 0) {
bytes[position++] = 1;
}
int nRemainingNulls = nulls % 255;
if (nRemainingNulls > 0) {
- byte nNullByte = SortOrder.invert((byte)(nRemainingNulls-1));
+ byte nNullByte = SortOrder.invert((byte)(nRemainingNulls - 1));
bytes[position++] = nNullByte;
}
return position;
}
-
- public static void writeEndSeperatorForVarLengthArray(DataOutputStream oStream) throws IOException {
- oStream.write(QueryConstants.SEPARATOR_BYTE);
- oStream.write(QueryConstants.SEPARATOR_BYTE);
+
+ public static void writeEndSeperatorForVarLengthArray(DataOutputStream oStream, SortOrder sortOrder) throws IOException {
+ writeEndSeperatorForVarLengthArray(oStream, sortOrder, true);
+ }
+
+ private static void writeEndSeperatorForVarLengthArray(DataOutputStream oStream, SortOrder sortOrder, boolean rowKeyOrderOptimizable)
+ throws IOException {
+ byte sepByte = getSeparatorByte(rowKeyOrderOptimizable, sortOrder);
+ oStream.write(sepByte);
+ oStream.write(sepByte);
}
- public static boolean useShortForOffsetArray(int maxOffset) {
- // If the max offset is less than Short.MAX_VALUE then offset array can use short
- if (maxOffset <= (2 * Short.MAX_VALUE)) {
- return true;
- }
- // else offset array can use Int
- return false;
- }
-
- public int toBytes(Object object, byte[] bytes, int offset) {
- PhoenixArray array = (PhoenixArray)object;
- if (array == null || array.baseType == null) {
- return 0;
- }
- return estimateByteSize(object, null, PDataType.fromTypeId((array.baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE)));
- }
+ public static boolean useShortForOffsetArray(int maxOffset) {
+ // If the max offset is less than Short.MAX_VALUE then offset array can use short
+ if (maxOffset <= (2 * Short.MAX_VALUE)) { return true; }
+ // else offset array can use Int
+ return false;
+ }
- // Estimates the size of the given array and also calculates the number of nulls and its repetition factor
+ @Override
+ public int toBytes(Object object, byte[] bytes, int offset) {
+ PhoenixArray array = (PhoenixArray)object;
+ if (array == null || array.baseType == null) { return 0; }
+ return estimateByteSize(object, null,
+ PDataType.fromTypeId((array.baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE)));
+ }
+
+ // Estimates the size of the given array and also calculates the number of nulls and its repetition factor
public int estimateByteSize(Object o, Pair<Integer, Integer> nullsVsNullRepeationCounter, PDataType baseType) {
if (baseType.isFixedWidth()) { return baseType.getByteSize(); }
if (baseType.isArrayType()) {
@@ -201,43 +236,41 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
// Non fixed width types must override this
throw new UnsupportedOperationException();
}
-
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- return targetType.isCoercibleTo(targetType, value);
- }
-
- public boolean isCoercibleTo(PDataType targetType, PDataType expectedTargetType) {
- if(!targetType.isArrayType()) {
- return false;
- } else {
- PDataType targetElementType = PDataType.fromTypeId(targetType.getSqlType()
- - PDataType.ARRAY_TYPE_BASE);
- PDataType expectedTargetElementType = PDataType.fromTypeId(expectedTargetType
- .getSqlType() - PDataType.ARRAY_TYPE_BASE);
- return expectedTargetElementType.isCoercibleTo(targetElementType);
- }
+
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ return targetType.isCoercibleTo(targetType, value);
}
- @Override
- public boolean isSizeCompatible(ImmutableBytesWritable ptr, Object value,
- PDataType srcType, Integer maxLength, Integer scale,
- Integer desiredMaxLength, Integer desiredScale) {
- if (value == null) return true;
- PhoenixArray pArr = (PhoenixArray) value;
- PDataType baseType = PDataType.fromTypeId(srcType.getSqlType() - PDataType.ARRAY_TYPE_BASE);
- for (int i = 0 ; i < pArr.numElements; i++) {
- Object val = pArr.getElement(i);
- if (!baseType.isSizeCompatible(ptr, val, baseType, srcType.getMaxLength(val),
- scale, desiredMaxLength, desiredScale)) {
- return false;
- }
- }
- return true;
- }
-
- public void coerceBytes(ImmutableBytesWritable ptr, Object value, PDataType actualType, Integer maxLength,
- Integer scale, Integer desiredMaxLength, Integer desiredScale, PDataType desiredType,
- SortOrder actualModifer, SortOrder expectedModifier) {
+ public boolean isCoercibleTo(PDataType targetType, PDataType expectedTargetType) {
+ if (!targetType.isArrayType()) {
+ return false;
+ } else {
+ PDataType targetElementType = PDataType.fromTypeId(targetType.getSqlType() - PDataType.ARRAY_TYPE_BASE);
+ PDataType expectedTargetElementType = PDataType.fromTypeId(expectedTargetType.getSqlType()
+ - PDataType.ARRAY_TYPE_BASE);
+ return expectedTargetElementType.isCoercibleTo(targetElementType);
+ }
+ }
+
+ @Override
+ public boolean isSizeCompatible(ImmutableBytesWritable ptr, Object value, PDataType srcType, Integer maxLength,
+ Integer scale, Integer desiredMaxLength, Integer desiredScale) {
+ if (value == null) return true;
+ PhoenixArray pArr = (PhoenixArray)value;
+ PDataType baseType = PDataType.fromTypeId(srcType.getSqlType() - PDataType.ARRAY_TYPE_BASE);
+ for (int i = 0; i < pArr.numElements; i++) {
+ Object val = pArr.getElement(i);
+ if (!baseType.isSizeCompatible(ptr, val, baseType, srcType.getMaxLength(val), scale, desiredMaxLength,
+ desiredScale)) { return false; }
+ }
+ return true;
+ }
+
+ private void coerceBytes(ImmutableBytesWritable ptr, Object value, PDataType actualType, Integer maxLength,
+ Integer scale, Integer desiredMaxLength, Integer desiredScale, PDataType desiredType,
+ SortOrder actualSortOrder, SortOrder desiredSortOrder,
+ boolean expectedRowKeyOrderOptimizable) {
if (ptr.getLength() == 0) { // a zero length ptr means null which will not be coerced to anything different
return;
}
@@ -245,42 +278,62 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
PDataType desiredBaseType = PDataType.fromTypeId(desiredType.getSqlType() - PDataType.ARRAY_TYPE_BASE);
if ((Objects.equal(maxLength, desiredMaxLength) || maxLength == null || desiredMaxLength == null)
&& actualType.isBytesComparableWith(desiredType)
- && baseType.isFixedWidth() == desiredBaseType.isFixedWidth() && actualModifer == expectedModifier) {
+ && baseType.isFixedWidth() == desiredBaseType.isFixedWidth()
+ && actualSortOrder == desiredSortOrder
+ && (desiredSortOrder == SortOrder.ASC || desiredBaseType.isFixedWidth() || isRowKeyOrderOptimized(actualType, actualSortOrder, ptr) == expectedRowKeyOrderOptimizable)) {
return;
}
+ PhoenixArray pArr;
if (value == null || actualType != desiredType) {
- value = toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), baseType, actualModifer, maxLength,
+ value = toObject(ptr.get(), ptr.getOffset(), ptr.getLength(), baseType, actualSortOrder, maxLength,
desiredScale, desiredBaseType);
- PhoenixArray pArr = (PhoenixArray)value;
+ pArr = (PhoenixArray)value;
// VARCHAR <=> CHAR
- if(baseType.isFixedWidth() != desiredBaseType.isFixedWidth()) {
+ if (baseType.isFixedWidth() != desiredBaseType.isFixedWidth()) {
if (!pArr.isPrimitiveType()) {
pArr = new PhoenixArray(pArr, desiredMaxLength);
}
}
- //Coerce to new max length when only max lengths differ
- if(actualType == desiredType && !pArr.isPrimitiveType() && maxLength != null && maxLength != desiredMaxLength){
- pArr = new PhoenixArray(pArr, desiredMaxLength);
+ // Coerce to new max length when only max lengths differ
+ if (actualType == desiredType && !pArr.isPrimitiveType() && maxLength != null
+ && maxLength != desiredMaxLength) {
+ pArr = new PhoenixArray(pArr, desiredMaxLength);
}
baseType = desiredBaseType;
- ptr.set(toBytes(pArr, baseType, expectedModifier));
} else {
- PhoenixArray pArr = (PhoenixArray)value;
+ pArr = (PhoenixArray)value;
pArr = new PhoenixArray(pArr, desiredMaxLength);
- ptr.set(toBytes(pArr, baseType, expectedModifier));
}
+ ptr.set(toBytes(pArr, baseType, desiredSortOrder, expectedRowKeyOrderOptimizable));
}
+ public static boolean isRowKeyOrderOptimized(PDataType type, SortOrder sortOrder, ImmutableBytesWritable ptr) {
+ return isRowKeyOrderOptimized(type, sortOrder, ptr.get(), ptr.getOffset(), ptr.getLength());
+ }
+
+ public static boolean isRowKeyOrderOptimized(PDataType type, SortOrder sortOrder, byte[] buf, int offset, int length) {
+ PDataType baseType = PDataType.fromTypeId(type.getSqlType() - PDataType.ARRAY_TYPE_BASE);
+ return isRowKeyOrderOptimized(baseType.isFixedWidth(), sortOrder, buf, offset, length);
+ }
+
+ private static boolean isRowKeyOrderOptimized(boolean isFixedWidth, SortOrder sortOrder, byte[] buf, int offset, int length) {
+ if (length == 0 || sortOrder == SortOrder.ASC || isFixedWidth) {
+ return true;
+ }
+ int offsetToHeaderOffset = offset + length - Bytes.SIZEOF_BYTE - Bytes.SIZEOF_INT * 2;
+ int offsetToSeparatorByte = Bytes.readAsInt(buf, offsetToHeaderOffset, Bytes.SIZEOF_INT) - 1;
+ return buf[offsetToSeparatorByte] == QueryConstants.DESC_SEPARATOR_BYTE;
+ }
+ @Override
public Object toObject(String value) {
- throw new IllegalArgumentException("This operation is not suppported");
- }
+ throw new IllegalArgumentException("This operation is not suppported");
+ }
- public Object toObject(byte[] bytes, int offset, int length, PDataType baseType,
- SortOrder sortOrder, Integer maxLength, Integer scale, PDataType desiredDataType) {
- return createPhoenixArray(bytes, offset, length, sortOrder,
- baseType, maxLength, desiredDataType);
- }
+ public Object toObject(byte[] bytes, int offset, int length, PDataType baseType, SortOrder sortOrder,
+ Integer maxLength, Integer scale, PDataType desiredDataType) {
+ return createPhoenixArray(bytes, offset, length, sortOrder, baseType, maxLength, desiredDataType);
+ }
public static boolean positionAtArrayElement(Tuple tuple, ImmutableBytesWritable ptr, int index,
Expression arrayExpr, PDataType pDataType, Integer maxLen) {
@@ -293,13 +346,14 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
positionAtArrayElement(ptr, index - 1, pDataType, maxLen);
return true;
}
+
public static void positionAtArrayElement(ImmutableBytesWritable ptr, int arrayIndex, PDataType baseDataType,
- Integer byteSize) {
+ Integer byteSize) {
byte[] bytes = ptr.get();
int initPos = ptr.getOffset();
if (!baseDataType.isFixedWidth()) {
- int noOfElements = Bytes.toInt(bytes, (ptr.getOffset() + ptr.getLength() - (Bytes.SIZEOF_BYTE + Bytes.SIZEOF_INT)),
- Bytes.SIZEOF_INT);
+ int noOfElements = Bytes.toInt(bytes,
+ (ptr.getOffset() + ptr.getLength() - (Bytes.SIZEOF_BYTE + Bytes.SIZEOF_INT)), Bytes.SIZEOF_INT);
boolean useShort = true;
if (noOfElements < 0) {
noOfElements = -noOfElements;
@@ -312,7 +366,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
int indexOffset = Bytes.toInt(bytes,
(ptr.getOffset() + ptr.getLength() - (Bytes.SIZEOF_BYTE + 2 * Bytes.SIZEOF_INT))) + ptr.getOffset();
- if(arrayIndex >= noOfElements) {
+ if (arrayIndex >= noOfElements) {
ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
} else {
// Skip those many offsets as given in the arrayIndex
@@ -343,9 +397,9 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
}
}
}
-
+
public static void positionAtArrayElement(ImmutableBytesWritable ptr, int arrayIndex, PDataType baseDataType,
- Integer byteSize, int offset, int length, int noOfElements, boolean first) {
+ Integer byteSize, int offset, int length, int noOfElements, boolean first) {
byte[] bytes = ptr.get();
if (!baseDataType.isFixedWidth()) {
int indexOffset = Bytes.toInt(bytes, (offset + length - (Bytes.SIZEOF_BYTE + 2 * Bytes.SIZEOF_INT)))
@@ -401,10 +455,10 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
return Bytes.toInt(bytes, offset, Bytes.SIZEOF_INT);
}
}
-
- private static int getOffset(ByteBuffer indexBuffer, int arrayIndex, boolean useShort, int indexOffset ) {
+
+ private static int getOffset(ByteBuffer indexBuffer, int arrayIndex, boolean useShort, int indexOffset) {
int offset;
- if(useShort) {
+ if (useShort) {
offset = indexBuffer.getShort() + Short.MAX_VALUE;
} else {
offset = indexBuffer.getInt();
@@ -412,20 +466,22 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
return offset;
}
- public Object toObject(Object object, PDataType actualType) {
- return object;
- }
-
- public Object toObject(Object object, PDataType actualType, SortOrder sortOrder) {
- // How to use the sortOrder ? Just reverse the elements
- return toObject(object, actualType);
- }
-
- /**
- * creates array bytes
- */
+ @Override
+ public Object toObject(Object object, PDataType actualType) {
+ return object;
+ }
+
+ public Object toObject(Object object, PDataType actualType, SortOrder sortOrder) {
+ // How to use the sortOrder ? Just reverse the elements
+ return toObject(object, actualType);
+ }
+
+ /**
+ * creates array bytes
+ * @param rowKeyOrderOptimizable TODO
+ */
private byte[] createArrayBytes(TrustedByteArrayOutputStream byteStream, DataOutputStream oStream,
- PhoenixArray array, int noOfElements, PDataType baseType, SortOrder sortOrder) {
+ PhoenixArray array, int noOfElements, PDataType baseType, SortOrder sortOrder, boolean rowKeyOrderOptimizable) {
try {
if (!baseType.isFixedWidth()) {
int[] offsetPos = new int[noOfElements];
@@ -442,11 +498,11 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
SortOrder.invert(bytes, 0, bytes, 0, bytes.length);
}
oStream.write(bytes, 0, bytes.length);
- oStream.write(QueryConstants.SEPARATOR_BYTE);
+ oStream.write(getSeparatorByte(rowKeyOrderOptimizable, sortOrder));
}
}
// Double seperator byte to show end of the non null array
- PArrayDataType.writeEndSeperatorForVarLengthArray(oStream);
+ writeEndSeperatorForVarLengthArray(oStream, sortOrder, rowKeyOrderOptimizable);
noOfElements = PArrayDataType.serailizeOffsetArrayIntoStream(oStream, byteStream, noOfElements,
offsetPos[offsetPos.length - 1], offsetPos);
serializeHeaderInfoIntoStream(oStream, noOfElements);
@@ -475,7 +531,8 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
return null;
}
- public static boolean appendItemToArray(ImmutableBytesWritable ptr, int length, int offset, byte[] arrayBytes, PDataType baseType, int arrayLength, Integer maxLength, SortOrder sortOrder) {
+ public static boolean appendItemToArray(ImmutableBytesWritable ptr, int length, int offset, byte[] arrayBytes,
+ PDataType baseType, int arrayLength, Integer maxLength, SortOrder sortOrder) {
if (ptr.getLength() == 0) {
ptr.set(arrayBytes, offset, length);
return true;
@@ -483,7 +540,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
int elementLength = maxLength == null ? ptr.getLength() : maxLength;
- //padding
+ // padding
if (elementLength > ptr.getLength()) {
baseType.pad(ptr, elementLength, sortOrder);
}
@@ -494,10 +551,12 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
byte[] newArray;
if (!baseType.isFixedWidth()) {
- int offsetArrayPosition = Bytes.toInt(arrayBytes, offset + length - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
- int offsetArrayLength = length - offsetArrayPosition - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE;
+ int offsetArrayPosition = Bytes.toInt(arrayBytes, offset + length - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT
+ - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
+ int offsetArrayLength = length - offsetArrayPosition - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT
+ - Bytes.SIZEOF_BYTE;
- //checks whether offset array consists of shorts or integers
+ // checks whether offset array consists of shorts or integers
boolean useInt = offsetArrayLength / Math.abs(arrayLength) == Bytes.SIZEOF_INT;
boolean convertToInt = false;
@@ -507,7 +566,8 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
if (PArrayDataType.useShortForOffsetArray(newElementPosition)) {
newArray = new byte[length + elementLength + Bytes.SIZEOF_SHORT + Bytes.SIZEOF_BYTE];
} else {
- newArray = new byte[length + elementLength + arrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
+ newArray = new byte[length + elementLength + arrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT
+ + Bytes.SIZEOF_BYTE];
convertToInt = true;
}
} else {
@@ -517,24 +577,35 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
int newOffsetArrayPosition = newElementPosition + elementLength + 3 * Bytes.SIZEOF_BYTE;
System.arraycopy(arrayBytes, offset, newArray, 0, newElementPosition);
+ // Write separator explicitly, as it may not be 0
+ byte sepByte = getSeparatorByte(isRowKeyOrderOptimized(false, sortOrder, arrayBytes, offset, length), sortOrder);
+ newArray[newOffsetArrayPosition-3] = sepByte; // Separator for new value
+ newArray[newOffsetArrayPosition-2] = sepByte; // Double byte separator
+ newArray[newOffsetArrayPosition-1] = sepByte;
System.arraycopy(elementBytes, elementOffset, newArray, newElementPosition, elementLength);
- arrayLength = (Math.abs(arrayLength) + 1) * (int) Math.signum(arrayLength);
+ arrayLength = (Math.abs(arrayLength) + 1) * (int)Math.signum(arrayLength);
if (useInt) {
- System.arraycopy(arrayBytes, offset + offsetArrayPosition, newArray, newOffsetArrayPosition, offsetArrayLength);
+ System.arraycopy(arrayBytes, offset + offsetArrayPosition, newArray, newOffsetArrayPosition,
+ offsetArrayLength);
Bytes.putInt(newArray, newOffsetArrayPosition + offsetArrayLength, newElementPosition);
- writeEndBytes(newArray, newOffsetArrayPosition, offsetArrayLength, arrayLength, arrayBytes[offset + length - 1], true);
+ writeEndBytes(newArray, newOffsetArrayPosition, offsetArrayLength, arrayLength, arrayBytes[offset
+ + length - 1], true);
} else {
if (!convertToInt) {
- System.arraycopy(arrayBytes, offset + offsetArrayPosition, newArray, newOffsetArrayPosition, offsetArrayLength);
- Bytes.putShort(newArray, newOffsetArrayPosition + offsetArrayLength, (short) (newElementPosition - Short.MAX_VALUE));
+ System.arraycopy(arrayBytes, offset + offsetArrayPosition, newArray, newOffsetArrayPosition,
+ offsetArrayLength);
+ Bytes.putShort(newArray, newOffsetArrayPosition + offsetArrayLength,
+ (short)(newElementPosition - Short.MAX_VALUE));
- writeEndBytes(newArray, newOffsetArrayPosition, offsetArrayLength, arrayLength, arrayBytes[offset + length - 1], false);
+ writeEndBytes(newArray, newOffsetArrayPosition, offsetArrayLength, arrayLength, arrayBytes[offset
+ + length - 1], false);
} else {
int off = newOffsetArrayPosition;
for (int arrayIndex = 0; arrayIndex < Math.abs(arrayLength) - 1; arrayIndex++) {
- Bytes.putInt(newArray, off, getOffset(arrayBytes, arrayIndex, true, offsetArrayPosition + offset));
+ Bytes.putInt(newArray, off,
+ getOffset(arrayBytes, arrayIndex, true, offsetArrayPosition + offset));
off += Bytes.SIZEOF_INT;
}
@@ -557,7 +628,8 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
return true;
}
- private static void writeEndBytes(byte[] array, int newOffsetArrayPosition, int offsetArrayLength, int arrayLength, byte header, boolean useInt) {
+ private static void writeEndBytes(byte[] array, int newOffsetArrayPosition, int offsetArrayLength, int arrayLength,
+ byte header, boolean useInt) {
int byteSize = useInt ? Bytes.SIZEOF_INT : Bytes.SIZEOF_SHORT;
Bytes.putInt(array, newOffsetArrayPosition + offsetArrayLength + byteSize, newOffsetArrayPosition);
@@ -565,12 +637,13 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
Bytes.putByte(array, newOffsetArrayPosition + offsetArrayLength + byteSize + 2 * Bytes.SIZEOF_INT, header);
}
- public static boolean prependItemToArray(ImmutableBytesWritable ptr, int length, int offset, byte[] arrayBytes, PDataType baseType, int arrayLength, Integer maxLength, SortOrder sortOrder) {
+ public static boolean prependItemToArray(ImmutableBytesWritable ptr, int length, int offset, byte[] arrayBytes,
+ PDataType baseType, int arrayLength, Integer maxLength, SortOrder sortOrder) {
int elementLength = maxLength == null ? ptr.getLength() : maxLength;
if (ptr.getLength() == 0) {
elementLength = 0;
}
- //padding
+ // padding
if (elementLength > ptr.getLength()) {
baseType.pad(ptr, elementLength, sortOrder);
}
@@ -579,28 +652,31 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
byte[] newArray;
if (!baseType.isFixedWidth()) {
- int offsetArrayPosition = Bytes.toInt(arrayBytes, offset + length - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
- int offsetArrayLength = length - offsetArrayPosition - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE;
+ int offsetArrayPosition = Bytes.toInt(arrayBytes, offset + length - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT
+ - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
+ int offsetArrayLength = length - offsetArrayPosition - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT
+ - Bytes.SIZEOF_BYTE;
arrayLength = Math.abs(arrayLength);
- //checks whether offset array consists of shorts or integers
+ // checks whether offset array consists of shorts or integers
boolean useInt = offsetArrayLength / arrayLength == Bytes.SIZEOF_INT;
boolean convertToInt = false;
- int endElementPosition = getOffset(arrayBytes, arrayLength - 1, !useInt, offsetArrayPosition + offset) + elementLength + Bytes.SIZEOF_BYTE;
+ int endElementPosition = getOffset(arrayBytes, arrayLength - 1, !useInt, offsetArrayPosition + offset)
+ + elementLength + Bytes.SIZEOF_BYTE;
int newOffsetArrayPosition;
int lengthIncrease;
int firstNonNullElementPosition = 0;
int currentPosition = 0;
- //handle the case where prepended element is null
+ // handle the case where prepended element is null
if (elementLength == 0) {
int nulls = 1;
- //counts the number of nulls which are already at the beginning of the array
+ // counts the number of nulls which are already at the beginning of the array
for (int index = 0; index < arrayLength; index++) {
int currOffset = getOffset(arrayBytes, index, !useInt, offsetArrayPosition + offset);
if (arrayBytes[offset + currOffset] == QueryConstants.SEPARATOR_BYTE) {
nulls++;
} else {
- //gets the offset of the first element after nulls at the beginning
+ // gets the offset of the first element after nulls at the beginning
firstNonNullElementPosition = currOffset;
break;
}
@@ -609,26 +685,31 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
int nMultiplesOver255 = nulls / 255;
int nRemainingNulls = nulls % 255;
- //Calculates the increase in length due to prepending the null
- //There is a length increase only when nRemainingNulls == 1
- //nRemainingNulls == 1 and nMultiplesOver255 == 0 means there were no nulls at the beginning previously.
- //At that case we need to increase the length by two bytes, one for separator byte and one for null count.
- //ex: initial array - 65 0 66 0 0 0 after prepending null - 0 1(inverted) 65 0 66 0 0 0
- //nRemainingNulls == 1 and nMultiplesOver255 != 0 means there were null at the beginning previously.
- //In this case due to prepending nMultiplesOver255 is increased by 1.
- //We need to increase the length by one byte to store increased that.
- //ex: initial array - 0 1 65 0 66 0 0 0 after prepending null - 0 1 1(inverted) 65 0 66 0 0 0
- //nRemainingNulls == 0 case.
- //ex: initial array - 0 254(inverted) 65 0 66 0 0 0 after prepending null - 0 1 65 0 66 0 0 0
- //nRemainingNulls > 1 case.
- //ex: initial array - 0 45(inverted) 65 0 66 0 0 0 after prepending null - 0 46(inverted) 65 0 66 0 0 0
- lengthIncrease = nRemainingNulls == 1 ? (nMultiplesOver255 == 0 ? 2 * Bytes.SIZEOF_BYTE : Bytes.SIZEOF_BYTE) : 0;
- endElementPosition = getOffset(arrayBytes, arrayLength - 1, !useInt, offsetArrayPosition + offset) + lengthIncrease;
+ // Calculates the increase in length due to prepending the null
+ // There is a length increase only when nRemainingNulls == 1
+ // nRemainingNulls == 1 and nMultiplesOver255 == 0 means there were no nulls at the beginning
+ // previously.
+ // At that case we need to increase the length by two bytes, one for separator byte and one for null
+ // count.
+ // ex: initial array - 65 0 66 0 0 0 after prepending null - 0 1(inverted) 65 0 66 0 0 0
+ // nRemainingNulls == 1 and nMultiplesOver255 != 0 means there were null at the beginning previously.
+ // In this case due to prepending nMultiplesOver255 is increased by 1.
+ // We need to increase the length by one byte to store increased that.
+ // ex: initial array - 0 1 65 0 66 0 0 0 after prepending null - 0 1 1(inverted) 65 0 66 0 0 0
+ // nRemainingNulls == 0 case.
+ // ex: initial array - 0 254(inverted) 65 0 66 0 0 0 after prepending null - 0 1 65 0 66 0 0 0
+ // nRemainingNulls > 1 case.
+ // ex: initial array - 0 45(inverted) 65 0 66 0 0 0 after prepending null - 0 46(inverted) 65 0 66 0 0 0
+ lengthIncrease = nRemainingNulls == 1 ? (nMultiplesOver255 == 0 ? 2 * Bytes.SIZEOF_BYTE
+ : Bytes.SIZEOF_BYTE) : 0;
+ endElementPosition = getOffset(arrayBytes, arrayLength - 1, !useInt, offsetArrayPosition + offset)
+ + lengthIncrease;
if (!useInt) {
if (PArrayDataType.useShortForOffsetArray(endElementPosition)) {
newArray = new byte[length + Bytes.SIZEOF_SHORT + lengthIncrease];
} else {
- newArray = new byte[length + arrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT + lengthIncrease];
+ newArray = new byte[length + arrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT
+ + lengthIncrease];
convertToInt = true;
}
} else {
@@ -638,14 +719,15 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
currentPosition++;
newOffsetArrayPosition = offsetArrayPosition + lengthIncrease;
- //serialize nulls at the beginning
+ // serialize nulls at the beginning
currentPosition = serializeNulls(newArray, currentPosition, nulls);
} else {
if (!useInt) {
if (PArrayDataType.useShortForOffsetArray(endElementPosition)) {
newArray = new byte[length + elementLength + Bytes.SIZEOF_SHORT + Bytes.SIZEOF_BYTE];
} else {
- newArray = new byte[length + elementLength + arrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
+ newArray = new byte[length + elementLength + arrayLength * Bytes.SIZEOF_SHORT
+ + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
convertToInt = true;
}
} else {
@@ -655,17 +737,22 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
lengthIncrease = elementLength + Bytes.SIZEOF_BYTE;
System.arraycopy(elementBytes, elementOffset, newArray, 0, elementLength);
+ // Explicitly set separator byte since for DESC it won't be 0.
+ newArray[elementLength] = getSeparatorByte(isRowKeyOrderOptimized(false, sortOrder, arrayBytes, offset, length), sortOrder);
currentPosition += elementLength + Bytes.SIZEOF_BYTE;
}
- System.arraycopy(arrayBytes, firstNonNullElementPosition + offset, newArray, currentPosition, offsetArrayPosition);
+ System.arraycopy(arrayBytes, firstNonNullElementPosition + offset, newArray, currentPosition,
+ offsetArrayPosition);
arrayLength = arrayLength + 1;
- //writes the new offset and changes the previous offsets
+ // writes the new offset and changes the previous offsets
if (useInt || convertToInt) {
- writeNewOffsets(arrayBytes, newArray, false, !useInt, newOffsetArrayPosition, arrayLength, offsetArrayPosition, offset, lengthIncrease, length);
+ writeNewOffsets(arrayBytes, newArray, false, !useInt, newOffsetArrayPosition, arrayLength,
+ offsetArrayPosition, offset, lengthIncrease, length);
} else {
- writeNewOffsets(arrayBytes, newArray, true, true, newOffsetArrayPosition, arrayLength, offsetArrayPosition, offset, lengthIncrease, length);
+ writeNewOffsets(arrayBytes, newArray, true, true, newOffsetArrayPosition, arrayLength,
+ offsetArrayPosition, offset, lengthIncrease, length);
}
} else {
newArray = new byte[length + elementLength];
@@ -678,11 +765,13 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
return true;
}
- private static void writeNewOffsets(byte[] arrayBytes, byte[] newArray, boolean useShortNew, boolean useShortPrevious, int newOffsetArrayPosition, int arrayLength, int offsetArrayPosition, int offset, int offsetShift, int length) {
+ private static void writeNewOffsets(byte[] arrayBytes, byte[] newArray, boolean useShortNew,
+ boolean useShortPrevious, int newOffsetArrayPosition, int arrayLength, int offsetArrayPosition, int offset,
+ int offsetShift, int length) {
int currentPosition = newOffsetArrayPosition;
int offsetArrayElementSize = useShortNew ? Bytes.SIZEOF_SHORT : Bytes.SIZEOF_INT;
if (useShortNew) {
- Bytes.putShort(newArray, currentPosition, (short) (0 - Short.MAX_VALUE));
+ Bytes.putShort(newArray, currentPosition, (short)(0 - Short.MAX_VALUE));
} else {
Bytes.putInt(newArray, currentPosition, 0);
}
@@ -693,13 +782,13 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
int oldOffset = getOffset(arrayBytes, arrayIndex, useShortPrevious, offsetArrayPosition + offset);
if (arrayBytes[offset + oldOffset] == QueryConstants.SEPARATOR_BYTE && nullsAtBeginning) {
if (useShortNew) {
- Bytes.putShort(newArray, currentPosition, (short) (oldOffset - Short.MAX_VALUE));
+ Bytes.putShort(newArray, currentPosition, (short)(oldOffset - Short.MAX_VALUE));
} else {
Bytes.putInt(newArray, currentPosition, oldOffset);
}
} else {
if (useShortNew) {
- Bytes.putShort(newArray, currentPosition, (short) (oldOffset + offsetShift - Short.MAX_VALUE));
+ Bytes.putShort(newArray, currentPosition, (short)(oldOffset + offsetShift - Short.MAX_VALUE));
} else {
Bytes.putInt(newArray, currentPosition, oldOffset + offsetShift);
}
@@ -715,7 +804,8 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
Bytes.putByte(newArray, currentPosition, arrayBytes[offset + length - 1]);
}
- public static boolean concatArrays(ImmutableBytesWritable ptr, int array1BytesLength, int array1BytesOffset, byte[] array1Bytes, PDataType baseType, int actualLengthOfArray1, int actualLengthOfArray2) {
+ public static boolean concatArrays(ImmutableBytesWritable ptr, int array1BytesLength, int array1BytesOffset,
+ byte[] array1Bytes, PDataType baseType, int actualLengthOfArray1, int actualLengthOfArray2) {
int array2BytesLength = ptr.getLength();
int array2BytesOffset = ptr.getOffset();
byte[] array2Bytes = ptr.get();
@@ -723,18 +813,22 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
byte[] newArray;
if (!baseType.isFixedWidth()) {
- int offsetArrayPositionArray1 = Bytes.toInt(array1Bytes, array1BytesOffset + array1BytesLength - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
- int offsetArrayPositionArray2 = Bytes.toInt(array2Bytes, array2BytesOffset + array2BytesLength - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
- int offsetArrayLengthArray1 = array1BytesLength - offsetArrayPositionArray1 - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE;
- int offsetArrayLengthArray2 = array2BytesLength - offsetArrayPositionArray2 - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE;
+ int offsetArrayPositionArray1 = Bytes.toInt(array1Bytes, array1BytesOffset + array1BytesLength
+ - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
+ int offsetArrayPositionArray2 = Bytes.toInt(array2Bytes, array2BytesOffset + array2BytesLength
+ - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
+ int offsetArrayLengthArray1 = array1BytesLength - offsetArrayPositionArray1 - Bytes.SIZEOF_INT
+ - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE;
+ int offsetArrayLengthArray2 = array2BytesLength - offsetArrayPositionArray2 - Bytes.SIZEOF_INT
+ - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE;
int newArrayLength = actualLengthOfArray1 + actualLengthOfArray2;
int nullsAtTheEndOfArray1 = 0;
int nullsAtTheBeginningOfArray2 = 0;
- //checks whether offset array consists of shorts or integers
+ // checks whether offset array consists of shorts or integers
boolean useIntArray1 = offsetArrayLengthArray1 / actualLengthOfArray1 == Bytes.SIZEOF_INT;
boolean useIntArray2 = offsetArrayLengthArray2 / actualLengthOfArray2 == Bytes.SIZEOF_INT;
boolean useIntNewArray = false;
- //count nulls at the end of array 1
+ // count nulls at the end of array 1
for (int index = actualLengthOfArray1 - 1; index > -1; index--) {
int offset = getOffset(array1Bytes, index, !useIntArray1, array1BytesOffset + offsetArrayPositionArray1);
if (array1Bytes[array1BytesOffset + offset] == QueryConstants.SEPARATOR_BYTE) {
@@ -743,7 +837,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
break;
}
}
- //count nulls at the beginning of the array 2
+ // count nulls at the beginning of the array 2
int array2FirstNonNullElementOffset = 0;
int array2FirstNonNullIndex = 0;
for (int index = 0; index < actualLengthOfArray2; index++) {
@@ -757,75 +851,95 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
}
}
int nullsInMiddleAfterConcat = nullsAtTheEndOfArray1 + nullsAtTheBeginningOfArray2;
- int bytesForNullsBefore = nullsAtTheBeginningOfArray2 / 255 + (nullsAtTheBeginningOfArray2 % 255 == 0 ? 0 : 1);
+ int bytesForNullsBefore = nullsAtTheBeginningOfArray2 / 255
+ + (nullsAtTheBeginningOfArray2 % 255 == 0 ? 0 : 1);
int bytesForNullsAfter = nullsInMiddleAfterConcat / 255 + (nullsInMiddleAfterConcat % 255 == 0 ? 0 : 1);
- //Increase of length required to store nulls
+ // Increase of length required to store nulls
int lengthIncreaseForNulls = bytesForNullsAfter - bytesForNullsBefore;
- //Length increase incremented by one when there were no nulls at the beginning of array and when there are
- //nulls at the end of array 1 as we need to allocate a byte for separator byte in this case.
- lengthIncreaseForNulls += nullsAtTheBeginningOfArray2 == 0 && nullsAtTheEndOfArray1 != 0 ? Bytes.SIZEOF_BYTE : 0;
- int newOffsetArrayPosition = offsetArrayPositionArray1 + offsetArrayPositionArray2 + lengthIncreaseForNulls - 2 * Bytes.SIZEOF_BYTE;
- int endElementPositionOfArray2 = getOffset(array2Bytes, actualLengthOfArray2 - 1, !useIntArray2, array2BytesOffset + offsetArrayPositionArray2);
- int newEndElementPosition = lengthIncreaseForNulls + endElementPositionOfArray2 + offsetArrayPositionArray1 - 2 * Bytes.SIZEOF_BYTE;
- //Creates a byre array to store the concatenated array
+ // Length increase incremented by one when there were no nulls at the beginning of array and when there are
+ // nulls at the end of array 1 as we need to allocate a byte for separator byte in this case.
+ lengthIncreaseForNulls += nullsAtTheBeginningOfArray2 == 0 && nullsAtTheEndOfArray1 != 0 ? Bytes.SIZEOF_BYTE
+ : 0;
+ int newOffsetArrayPosition = offsetArrayPositionArray1 + offsetArrayPositionArray2 + lengthIncreaseForNulls
+ - 2 * Bytes.SIZEOF_BYTE;
+ int endElementPositionOfArray2 = getOffset(array2Bytes, actualLengthOfArray2 - 1, !useIntArray2,
+ array2BytesOffset + offsetArrayPositionArray2);
+ int newEndElementPosition = lengthIncreaseForNulls + endElementPositionOfArray2 + offsetArrayPositionArray1
+ - 2 * Bytes.SIZEOF_BYTE;
+ // Creates a byte array to store the concatenated array
if (PArrayDataType.useShortForOffsetArray(newEndElementPosition)) {
- newArray = new byte[newOffsetArrayPosition + newArrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
+ newArray = new byte[newOffsetArrayPosition + newArrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT
+ + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
} else {
useIntNewArray = true;
- newArray = new byte[newOffsetArrayPosition + newArrayLength * Bytes.SIZEOF_INT + Bytes.SIZEOF_INT + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
+ newArray = new byte[newOffsetArrayPosition + newArrayLength * Bytes.SIZEOF_INT + Bytes.SIZEOF_INT
+ + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
}
int currentPosition = 0;
- //Copies all the elements from array 1 to new array
- System.arraycopy(array1Bytes, array1BytesOffset, newArray, currentPosition, offsetArrayPositionArray1 - 2 * Bytes.SIZEOF_BYTE);
+ // Copies all the elements from array 1 to new array
+ System.arraycopy(array1Bytes, array1BytesOffset, newArray, currentPosition, offsetArrayPositionArray1 - 2
+ * Bytes.SIZEOF_BYTE);
currentPosition = offsetArrayPositionArray1 - 2 * Bytes.SIZEOF_BYTE;
int array2StartingPosition = currentPosition;
currentPosition += nullsInMiddleAfterConcat != 0 ? 1 : 0;
- //Writes nulls in the middle of the array.
+ // Writes nulls in the middle of the array.
currentPosition = serializeNulls(newArray, currentPosition, nullsInMiddleAfterConcat);
- //Copies the elements from array 2 beginning from the first non null element.
- System.arraycopy(array2Bytes, array2BytesOffset + array2FirstNonNullElementOffset, newArray, currentPosition, offsetArrayPositionArray2 - array2FirstNonNullElementOffset);
+ // Copies the elements from array 2 beginning from the first non null element.
+ System.arraycopy(array2Bytes, array2BytesOffset + array2FirstNonNullElementOffset, newArray,
+ currentPosition, offsetArrayPositionArray2 - array2FirstNonNullElementOffset);
currentPosition += offsetArrayPositionArray2 - array2FirstNonNullElementOffset;
- //Writing offset arrays
+ // Writing offset arrays
if (useIntNewArray) {
- //offsets for the elements from array 1. Simply copied.
+ // offsets for the elements from array 1. Simply copied.
for (int index = 0; index < actualLengthOfArray1; index++) {
- int offset = getOffset(array1Bytes, index, !useIntArray1, array1BytesOffset + offsetArrayPositionArray1);
+ int offset = getOffset(array1Bytes, index, !useIntArray1, array1BytesOffset
+ + offsetArrayPositionArray1);
Bytes.putInt(newArray, currentPosition, offset);
currentPosition += Bytes.SIZEOF_INT;
}
- //offsets for nulls in the middle
+ // offsets for nulls in the middle
for (int index = 0; index < array2FirstNonNullIndex; index++) {
- int offset = getOffset(array2Bytes, index, !useIntArray2, array2BytesOffset + offsetArrayPositionArray2);
+ int offset = getOffset(array2Bytes, index, !useIntArray2, array2BytesOffset
+ + offsetArrayPositionArray2);
Bytes.putInt(newArray, currentPosition, offset + array2StartingPosition);
currentPosition += Bytes.SIZEOF_INT;
}
- //offsets for the elements from the first non null element from array 2
- int part2NonNullStartingPosition = array2StartingPosition + bytesForNullsAfter + (bytesForNullsAfter == 0 ? 0 : Bytes.SIZEOF_BYTE);
+ // offsets for the elements from the first non null element from array 2
+ int part2NonNullStartingPosition = array2StartingPosition + bytesForNullsAfter
+ + (bytesForNullsAfter == 0 ? 0 : Bytes.SIZEOF_BYTE);
for (int index = array2FirstNonNullIndex; index < actualLengthOfArray2; index++) {
- int offset = getOffset(array2Bytes, index, !useIntArray2, array2BytesOffset + offsetArrayPositionArray2);
- Bytes.putInt(newArray, currentPosition, offset - array2FirstNonNullElementOffset + part2NonNullStartingPosition);
+ int offset = getOffset(array2Bytes, index, !useIntArray2, array2BytesOffset
+ + offsetArrayPositionArray2);
+ Bytes.putInt(newArray, currentPosition, offset - array2FirstNonNullElementOffset
+ + part2NonNullStartingPosition);
currentPosition += Bytes.SIZEOF_INT;
}
} else {
- //offsets for the elements from array 1. Simply copied.
+ // offsets for the elements from array 1. Simply copied.
for (int index = 0; index < actualLengthOfArray1; index++) {
- int offset = getOffset(array1Bytes, index, !useIntArray1, array1BytesOffset + offsetArrayPositionArray1);
- Bytes.putShort(newArray, currentPosition, (short) (offset - Short.MAX_VALUE));
+ int offset = getOffset(array1Bytes, index, !useIntArray1, array1BytesOffset
+ + offsetArrayPositionArray1);
+ Bytes.putShort(newArray, currentPosition, (short)(offset - Short.MAX_VALUE));
currentPosition += Bytes.SIZEOF_SHORT;
}
- //offsets for nulls in the middle
+ // offsets for nulls in the middle
for (int index = 0; index < array2FirstNonNullIndex; index++) {
- int offset = getOffset(array2Bytes, index, !useIntArray2, array2BytesOffset + offsetArrayPositionArray2);
- Bytes.putShort(newArray, currentPosition, (short) (offset + array2StartingPosition - Short.MAX_VALUE));
+ int offset = getOffset(array2Bytes, index, !useIntArray2, array2BytesOffset
+ + offsetArrayPositionArray2);
+ Bytes.putShort(newArray, currentPosition,
+ (short)(offset + array2StartingPosition - Short.MAX_VALUE));
currentPosition += Bytes.SIZEOF_SHORT;
}
- //offsets for the elements from the first non null element from array 2
- int part2NonNullStartingPosition = array2StartingPosition + bytesForNullsAfter + (bytesForNullsAfter == 0 ? 0 : Bytes.SIZEOF_BYTE);
+ // offsets for the elements from the first non null element from array 2
+ int part2NonNullStartingPosition = array2StartingPosition + bytesForNullsAfter
+ + (bytesForNullsAfter == 0 ? 0 : Bytes.SIZEOF_BYTE);
for (int index = array2FirstNonNullIndex; index < actualLengthOfArray2; index++) {
- int offset = getOffset(array2Bytes, index, !useIntArray2, array2BytesOffset + offsetArrayPositionArray2);
- Bytes.putShort(newArray, currentPosition, (short) (offset - array2FirstNonNullElementOffset + part2NonNullStartingPosition - Short.MAX_VALUE));
+ int offset = getOffset(array2Bytes, index, !useIntArray2, array2BytesOffset
+ + offsetArrayPositionArray2);
+ Bytes.putShort(newArray, currentPosition, (short)(offset - array2FirstNonNullElementOffset
+ + part2NonNullStartingPosition - Short.MAX_VALUE));
currentPosition += Bytes.SIZEOF_SHORT;
}
}
@@ -856,7 +970,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
noOfElements = -noOfElements;
}
int off = 0;
- if(useInt) {
+ if (useInt) {
for (int pos : offsetPos) {
Bytes.putInt(offsetArr, off, pos);
off += Bytes.SIZEOF_INT;
@@ -886,9 +1000,9 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
oStream.write(ARRAY_SERIALIZATION_VERSION);
}
- public static int initOffsetArray(int noOfElements, int baseSize) {
- // for now create an offset array equal to the noofelements
- return noOfElements * baseSize;
+ public static int initOffsetArray(int noOfElements, int baseSize) {
+ // for now create an offset array equal to the noofelements
+ return noOfElements * baseSize;
}
// Any variable length array would follow the below order
@@ -898,11 +1012,11 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
// Trailing nulls are not taken into account
// The last non null element is followed by two seperator bytes
// For eg
- // a, b, null, null, c, null would be
+ // a, b, null, null, c, null would be
// 65 0 66 0 0 2 67 0 0 0
// a null null null b c null d would be
// 65 0 0 3 66 0 67 0 0 1 68 0 0 0
- // Follow the above example to understand how this works
+ // Follow the above example to understand how this works
private Object createPhoenixArray(byte[] bytes, int offset, int length, SortOrder sortOrder,
PDataType baseDataType, Integer maxLength, PDataType desiredDataType) {
if (bytes == null || length == 0) { return null; }
@@ -990,45 +1104,43 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
}
}
}
- if(baseDataType == desiredDataType) {
+ if (baseDataType == desiredDataType) {
return PArrayDataType.instantiatePhoenixArray(baseDataType, elements);
} else {
return PArrayDataType.instantiatePhoenixArray(desiredDataType, elements);
}
}
-
+
public static PhoenixArray instantiatePhoenixArray(PDataType actualType, Object[] elements) {
return PDataType.instantiatePhoenixArray(actualType, elements);
}
-
- public int compareTo(Object lhs, Object rhs) {
- PhoenixArray lhsArr = (PhoenixArray) lhs;
- PhoenixArray rhsArr = (PhoenixArray) rhs;
- if(lhsArr.equals(rhsArr)) {
- return 0;
- }
- return 1;
- }
-
- public static int getArrayLength(ImmutableBytesWritable ptr,
- PDataType baseType, Integer maxLength) {
- byte[] bytes = ptr.get();
- if(baseType.isFixedWidth()) {
- int elemLength = maxLength == null ? baseType.getByteSize() : maxLength;
- return (ptr.getLength() / elemLength);
- }
- return Bytes.toInt(bytes, (ptr.getOffset() + ptr.getLength() - (Bytes.SIZEOF_BYTE + Bytes.SIZEOF_INT)));
- }
+
+ @Override
+ public int compareTo(Object lhs, Object rhs) {
+ PhoenixArray lhsArr = (PhoenixArray)lhs;
+ PhoenixArray rhsArr = (PhoenixArray)rhs;
+ if (lhsArr.equals(rhsArr)) { return 0; }
+ return 1;
+ }
+
+ public static int getArrayLength(ImmutableBytesWritable ptr, PDataType baseType, Integer maxLength) {
+ byte[] bytes = ptr.get();
+ if (baseType.isFixedWidth()) {
+ int elemLength = maxLength == null ? baseType.getByteSize() : maxLength;
+ return (ptr.getLength() / elemLength);
+ }
+ return Bytes.toInt(bytes, (ptr.getOffset() + ptr.getLength() - (Bytes.SIZEOF_BYTE + Bytes.SIZEOF_INT)));
+ }
public static int estimateSize(int size, PDataType baseType) {
- if(baseType.isFixedWidth()) {
+ if (baseType.isFixedWidth()) {
return baseType.getByteSize() * size;
} else {
return size * ValueSchema.ESTIMATED_VARIABLE_LENGTH_SIZE;
}
-
+
}
-
+
public Object getSampleValue(PDataType baseType, Integer arrayLength, Integer elemLength) {
Preconditions.checkArgument(arrayLength == null || arrayLength >= 0);
if (arrayLength == null) {
@@ -1047,17 +1159,18 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
PhoenixArray array = (PhoenixArray)o;
PDataType baseType = PDataType.arrayBaseType(this);
int len = array.getDimensions();
- if (len != 0) {
+ if (len != 0) {
for (int i = 0; i < len; i++) {
buf.append(baseType.toStringLiteral(array.getElement(i), null));
buf.append(',');
}
- buf.setLength(buf.length()-1);
+ buf.setLength(buf.length() - 1);
}
buf.append(']');
return buf.toString();
}
+ // FIXME: remove this duplicate code
static public class PArrayDataTypeBytesArrayBuilder<T> {
static private final int BYTE_ARRAY_DEFAULT_SIZE = 128;
@@ -1083,8 +1196,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
if (oStream != null) oStream.close();
byteStream = null;
oStream = null;
- } catch (IOException ioe) {
- }
+ } catch (IOException ioe) {}
}
public boolean appendElem(byte[] bytes) {
@@ -1105,7 +1217,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
SortOrder.invert(bytes, offset, bytes, offset, len);
}
oStream.write(bytes, offset, len);
- oStream.write(QueryConstants.SEPARATOR_BYTE);
+ oStream.write(getSeparatorByte(true, sortOrder));
}
} else {
if (sortOrder == SortOrder.DESC) {
@@ -1114,12 +1226,11 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
oStream.write(bytes, offset, len);
}
return true;
- } catch (IOException e) {
- }
+ } catch (IOException e) {}
return false;
}
- public byte[] getBytesAndClose() {
+ public byte[] getBytesAndClose(SortOrder sortOrder) {
try {
if (!baseType.isFixedWidth()) {
int noOfElements = offsetPos.size();
@@ -1129,18 +1240,15 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
offsetPosArray[index] = i;
++index;
}
- PArrayDataType.writeEndSeperatorForVarLengthArray(oStream);
- noOfElements =
- PArrayDataType.serailizeOffsetArrayIntoStream(oStream, byteStream,
- noOfElements, offsetPosArray[offsetPosArray.length - 1],
- offsetPosArray);
+ PArrayDataType.writeEndSeperatorForVarLengthArray(oStream, sortOrder);
+ noOfElements = PArrayDataType.serailizeOffsetArrayIntoStream(oStream, byteStream, noOfElements,
+ offsetPosArray[offsetPosArray.length - 1], offsetPosArray);
serializeHeaderInfoIntoStream(oStream, noOfElements);
}
ImmutableBytesWritable ptr = new ImmutableBytesWritable();
ptr.set(byteStream.getBuffer(), 0, byteStream.size());
return ByteUtil.copyKeyBytesIfNecessary(ptr);
- } catch (IOException e) {
- } finally {
+ } catch (IOException e) {} finally {
close();
}
return null;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java
index 16c6485..523f774 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java
@@ -17,92 +17,70 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PBinaryArray extends PArrayDataType<byte[][]> {
- public static final PBinaryArray INSTANCE = new PBinaryArray();
-
- private PBinaryArray() {
- super("BINARY ARRAY", PDataType.ARRAY_TYPE_BASE + PBinary.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 28);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PBinaryArray INSTANCE = new PBinaryArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PBinaryArray() {
+ super("BINARY ARRAY", PDataType.ARRAY_TYPE_BASE + PBinary.INSTANCE.getSqlType(), PhoenixArray.class, null, 28);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PBinary.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
- return toObject(bytes, offset, length, PBinary.INSTANCE, sortOrder, maxLength, scale,
- PBinary.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PBinary.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] charArr = (Object[]) pArr.array;
- for (Object i : charArr) {
- if (!super.isCoercibleTo(PBinary.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder,
+ Integer maxLength, Integer scale) {
+ return toObject(bytes, offset, length, PBinary.INSTANCE, sortOrder, maxLength, scale, PBinary.INSTANCE);
}
- return true;
- }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) { return true; }
+ PhoenixArray pArr = (PhoenixArray)value;
+ Object[] charArr = (Object[])pArr.array;
+ for (Object i : charArr) {
+ if (!super.isCoercibleTo(PBinary.INSTANCE, i)) { return false; }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PBinary.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PBinary.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java
index 87bf9b4..742b0de 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java
@@ -17,93 +17,71 @@
*/
package org.apache.phoenix.schema.types;
-import java.sql.Types;
-
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.types.PhoenixArray.PrimitiveBooleanPhoenixArray;
public class PBooleanArray extends PArrayDataType<boolean[]> {
- public static final PBooleanArray INSTANCE = new PBooleanArray();
+ public static final PBooleanArray INSTANCE = new PBooleanArray();
- private PBooleanArray() {
- super("BOOLEAN ARRAY", PDataType.ARRAY_TYPE_BASE + PBoolean.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 25);
- }
+ private PBooleanArray() {
+ super("BOOLEAN ARRAY", PDataType.ARRAY_TYPE_BASE + PBoolean.INSTANCE.getSqlType(), PhoenixArray.class, null, 25);
+ }
- @Override
- public boolean isArrayType() {
- return true;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PBoolean.INSTANCE, sortOrder);
- }
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PBoolean.INSTANCE, sortOrder);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
- return toObject(bytes, offset, length, PBoolean.INSTANCE, sortOrder, maxLength, scale,
- PBoolean.INSTANCE);
- }
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder,
+ Integer maxLength, Integer scale) {
+ return toObject(bytes, offset, length, PBoolean.INSTANCE, sortOrder, maxLength, scale, PBoolean.INSTANCE);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
@Override
public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
- }
- PrimitiveBooleanPhoenixArray pArr = (PrimitiveBooleanPhoenixArray) value;
- boolean[] booleanArr = (boolean[]) pArr.array;
+ if (value == null) { return true; }
+ PrimitiveBooleanPhoenixArray pArr = (PrimitiveBooleanPhoenixArray)value;
+ boolean[] booleanArr = (boolean[])pArr.array;
for (boolean b : booleanArr) {
- if (!super.isCoercibleTo(PInteger.INSTANCE, b)) {
- return false;
- }
+ if (!super.isCoercibleTo(PInteger.INSTANCE, b)) { return false; }
}
return true;
}
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
-
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
-
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PBoolean.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PBoolean.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java
index 89ec5db..a740c7f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java
@@ -17,92 +17,76 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PCharArray extends PArrayDataType<String[]> {
- public static final PCharArray INSTANCE = new PCharArray();
-
- private PCharArray() {
- super("CHAR ARRAY", PDataType.ARRAY_TYPE_BASE + PChar.INSTANCE.getSqlType(), PhoenixArray.class,
- null, 29);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PCharArray INSTANCE = new PCharArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PCharArray() {
+ super("CHAR ARRAY", PDataType.ARRAY_TYPE_BASE + PChar.INSTANCE.getSqlType(), PhoenixArray.class,
+ null, 29);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PChar.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
- return toObject(bytes, offset, length, PChar.INSTANCE, sortOrder, maxLength, scale,
- PChar.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PChar.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] charArr = (Object[]) pArr.array;
- for (Object i : charArr) {
- if (!super.isCoercibleTo(PChar.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
+ return toObject(bytes, offset, length, PChar.INSTANCE, sortOrder, maxLength, scale,
+ PChar.INSTANCE);
}
- return true;
- }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] charArr = (Object[]) pArr.array;
+ for (Object i : charArr) {
+ if (!super.isCoercibleTo(PChar.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PChar.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PChar.INSTANCE, arrayLength, maxLength);
+ }
}
[36/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns
Posted by ma...@apache.org.
PHOENIX-2067 Sort order incorrect for variable length DESC columns
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/4b99c632
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/4b99c632
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/4b99c632
Branch: refs/heads/calcite
Commit: 4b99c632c5e40251451e69fbe6d108f51e549e9e
Parents: 2620a80
Author: James Taylor <jt...@salesforce.com>
Authored: Tue Jul 14 13:40:58 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Tue Jul 14 13:40:58 2015 -0700
----------------------------------------------------------------------
.../org/apache/phoenix/util/UpgradeUtil.java | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/4b99c632/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
index e59ea98..0ad6b9d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/UpgradeUtil.java
@@ -80,12 +80,11 @@ import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.SaltingUtil;
import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.types.PBoolean;
+import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.schema.types.PDecimal;
-import org.apache.phoenix.schema.types.PDecimalArray;
import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PLong;
import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.schema.types.PVarcharArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -878,6 +877,20 @@ public class UpgradeUtil {
}
return otherTables;
}
+
+ // Return all types that are not fixed width that may need upgrading due to PHOENIX-2067
+ // We exclude VARBINARY as we no longer support DESC for it.
+ private static String getAffectedDataTypes() {
+ StringBuilder buf = new StringBuilder("(" + PVarchar.INSTANCE.getSqlType() + "," + PDecimal.INSTANCE.getSqlType() + ",");
+ for (PDataType type : PDataType.values()) {
+ if (type.isArrayType()) {
+ buf.append(type.getSqlType());
+ buf.append(',');
+ }
+ }
+ buf.setCharAt(buf.length()-1, ')');
+ return buf.toString();
+ }
/**
* Identify the tables that need to be upgraded due to PHOENIX-2067
*/
@@ -890,7 +903,7 @@ public class UpgradeUtil {
"WHERE COLUMN_NAME IS NOT NULL\n" +
"AND COLUMN_FAMILY IS NULL\n" +
"AND SORT_ORDER = " + SortOrder.DESC.getSystemValue() + "\n" +
- "AND DATA_TYPE IN (" + PVarchar.INSTANCE.getSqlType() + "," + PDecimal.INSTANCE.getSqlType() + "," + PVarcharArray.INSTANCE.getSqlType() + "," + PDecimalArray.INSTANCE.getSqlType() + ")\n" +
+ "AND DATA_TYPE IN " + getAffectedDataTypes() + "\n" +
"GROUP BY TENANT_ID,TABLE_SCHEM,TABLE_NAME");
Set<String> physicalTables = Sets.newHashSetWithExpectedSize(1024);
List<String> remainingTableNames = addPhysicalTables(conn, rs, PTableType.INDEX, physicalTables);
[13/50] [abbrv] phoenix git commit: PHOENIX-2058 Check for existence
and compatibility of columns being added in view
Posted by ma...@apache.org.
PHOENIX-2058 Check for existence and compatibility of columns being added in view
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/8c9a6b8c
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/8c9a6b8c
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/8c9a6b8c
Branch: refs/heads/calcite
Commit: 8c9a6b8cb94c0380c8e99aeee18d3b7d8f6e37ef
Parents: 61f1900
Author: Thomas D'Silva <td...@salesforce.com>
Authored: Thu Jul 2 21:19:11 2015 -0700
Committer: Thomas D'Silva <td...@salesforce.com>
Committed: Wed Jul 8 15:36:00 2015 -0700
----------------------------------------------------------------------
.../apache/phoenix/end2end/AlterTableIT.java | 221 +++++++++++++++++--
.../coprocessor/MetaDataEndpointImpl.java | 108 ++++++++-
.../apache/phoenix/schema/MetaDataClient.java | 4 +-
3 files changed, 302 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c9a6b8c/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 56bba9b..fbaded0 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
@@ -64,6 +64,7 @@ import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.ReadOnlyProps;
import org.apache.phoenix.util.SchemaUtil;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import com.google.common.base.Objects;
@@ -2009,7 +2010,7 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
@Test
- public void testAddColumnToTableWithViews() throws Exception {
+ public void testAddNewColumnToBaseTableWithViews() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
try {
conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
@@ -2020,12 +2021,176 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
+ " )");
assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
- conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 SMALLINT ) AS SELECT * FROM TABLEWITHVIEW");
- assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 4, 3, "ID", "COL1", "COL2", "VIEW_COL1");
+ conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR ) AS SELECT * FROM TABLEWITHVIEW");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD COL3 char(10)");
- assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 4, "ID", "COL1", "COL2", "COL3", "VIEW_COL1");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 6, 4, "ID", "COL1", "COL2", "COL3", "VIEW_COL1", "VIEW_COL2");
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testAddExistingViewColumnToBaseTableWithViews() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+ + " ID char(10) NOT NULL,"
+ + " COL1 integer NOT NULL,"
+ + " COL2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+ + " )");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
+
+ conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256), VIEW_COL3 VARCHAR, VIEW_COL4 DECIMAL ) AS SELECT * FROM TABLEWITHVIEW");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 7, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4");
+
+ // upsert single row into view
+ String dml = "UPSERT INTO VIEWOFTABLE VALUES(?,?,?,?,?, ?, ?)";
+ PreparedStatement stmt = conn.prepareStatement(dml);
+ stmt.setString(1, "view1");
+ stmt.setInt(2, 12);
+ stmt.setInt(3, 13);
+ stmt.setInt(4, 14);
+ stmt.setString(5, "view5");
+ stmt.setString(6, "view6");
+ stmt.setInt(7, 17);
+ stmt.execute();
+ conn.commit();
+
+ try {
+ // should fail because there is already a view column with same name of different type
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 char(10)");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there is already a view column with same name with a higher scale
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,1)");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there is already a view column with same name with a greater length
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 VARCHAR(256)");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ try {
+ // should fail because there is already a view column with null length
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 DECIMAL(9,2)");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ // validate that there were no columns added to the table or view
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 7, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4");
+
+ // should succeed because even though there already is a view column with same name,
+ // the column being added has a scale and max length that is equal to or greater
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR, VIEW_COL4 DECIMAL");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 4, -1, "ID", "COL1", "COL2", "VIEW_COL2", "VIEW_COL4");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 7, 5, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2", "VIEW_COL3", "VIEW_COL4");
+
+ // query table
+ ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "view1");
+ assertEquals(rs.getInt(2), 12);
+ assertEquals(rs.getInt(3), 13);
+ assertEquals(rs.getString(4), "view5");
+ assertEquals(rs.getInt(5), 17);
+ assertFalse(rs.next());
+
+ // query view
+ rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "view1");
+ assertEquals(rs.getInt(2), 12);
+ assertEquals(rs.getInt(3), 13);
+ assertEquals(rs.getInt(4), 14);
+ assertEquals(rs.getString(5),"view5");
+ assertEquals(rs.getString(6),"view6");
+ assertEquals(rs.getInt(7), 17);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ @Ignore
+ // enable this test after https://issues.apache.org/jira/browse/PHOENIX-978 is fixed
+ public void testAddExistingViewPkColumnToBaseTableWithViews() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+ + " ID char(10) NOT NULL,"
+ + " COL1 integer NOT NULL,"
+ + " COL2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+ + " )");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
+
+ conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR(256) CONSTRAINT pk PRIMARY KEY (VIEW_COL1, VIEW_COL2)) AS SELECT * FROM TABLEWITHVIEW");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+ // upsert single row into view
+ String dml = "UPSERT INTO VIEWOFTABLE VALUES(?,?,?,?,?)";
+ PreparedStatement stmt = conn.prepareStatement(dml);
+ stmt.setString(1, "view1");
+ stmt.setInt(2, 12);
+ stmt.setInt(3, 13);
+ stmt.setInt(4, 14);
+ stmt.setString(5, "view5");
+ stmt.execute();
+ conn.commit();
+
+ try {
+ // should fail because there is already a pk view column with same name is a different slot
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL2 VARCHAR PRIMARY KEY");
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+
+ // add the pk column of the view to the base table
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL PRIMARY KEY");
+ assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 4, -1, "ID", "COL1", "COL2", "VIEW_COL1");
+ assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 4, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
+
+ // query table
+ ResultSet rs = stmt.executeQuery("SELECT * FROM TABLEWITHVIEW");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "view1");
+ assertEquals(rs.getInt(2), 12);
+ assertEquals(rs.getInt(3), 13);
+ assertEquals(rs.getInt(4), 14);
+ assertFalse(rs.next());
+
+ // query view
+ rs = stmt.executeQuery("SELECT * FROM VIEWOFTABLE");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "view1");
+ assertEquals(rs.getInt(2), 12);
+ assertEquals(rs.getInt(3), 13);
+ assertEquals(rs.getInt(4), 14);
+ assertEquals(rs.getString(5),"view5");
+ assertFalse(rs.next());
} finally {
conn.close();
}
@@ -2045,34 +2210,46 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
ResultSet parentTableColumnsRs = null;
if (parentTableName != null) {
parentTableColumnsRs = conn.getMetaData().getColumns(null, null, parentTableName, null);
+ parentTableColumnsRs.next();
}
- rs = conn.getMetaData().getColumns(null, null, tableName, null);
+ ResultSet viewColumnsRs = conn.getMetaData().getColumns(null, null, tableName, null);
for (int i = 0; i < columnName.length; i++) {
if (columnName[i] != null) {
- assertTrue(rs.next());
- assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in columnName: i=" + i), columnName[i], rs.getString("COLUMN_NAME"));
- assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in ordinalPosition: i=" + i), i+1, rs.getInt("ORDINAL_POSITION"));
- if (i < baseColumnCount && parentTableColumnsRs != null) {
- assertTrue(parentTableColumnsRs.next());
- ResultSetMetaData md = parentTableColumnsRs.getMetaData();
- assertEquals(md.getColumnCount(), rs.getMetaData().getColumnCount());
- for (int columnIndex = 1; columnIndex < md.getColumnCount(); columnIndex++) {
- String viewColumnValue = rs.getString(columnIndex);
+ assertTrue(viewColumnsRs.next());
+ assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in columnName: i=" + i), columnName[i], viewColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_NAME));
+ assertEquals(getSystemCatalogEntriesForTable(conn, tableName, "Mismatch in ordinalPosition: i=" + i), i+1, viewColumnsRs.getInt(PhoenixDatabaseMetaData.ORDINAL_POSITION));
+ // validate that all the columns in the base table are present in the view
+ if (parentTableColumnsRs != null && !parentTableColumnsRs.isAfterLast()) {
+ ResultSetMetaData parentTableColumnsMetadata = parentTableColumnsRs.getMetaData();
+ assertEquals(parentTableColumnsMetadata.getColumnCount(), viewColumnsRs.getMetaData().getColumnCount());
+
+ // if you add a non-pk column that already exists in the view
+ if (!viewColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_NAME).equals(parentTableColumnsRs.getString(PhoenixDatabaseMetaData.COLUMN_NAME))) {
+ continue;
+ }
+
+ for (int columnIndex = 1; columnIndex < parentTableColumnsMetadata.getColumnCount(); columnIndex++) {
+ String viewColumnValue = viewColumnsRs.getString(columnIndex);
String parentTableColumnValue = parentTableColumnsRs.getString(columnIndex);
if (!Objects.equal(viewColumnValue, parentTableColumnValue)) {
- if (md.getColumnName(columnIndex).equals("TABLE_NAME")) {
+ if (parentTableColumnsMetadata.getColumnName(columnIndex).equals(PhoenixDatabaseMetaData.TABLE_NAME)) {
assertEquals(parentTableName, parentTableColumnValue);
assertEquals(tableName, viewColumnValue);
- } else {
- fail(md.getColumnName(columnIndex) + "=" + parentTableColumnValue);
+ }
+ else if (parentTableColumnsMetadata.getColumnName(columnIndex).equals(PhoenixDatabaseMetaData.ORDINAL_POSITION) && parentTableColumnsRs.getString("COLUMN_FAMILY")!=null) {
+ // its ok if the ordinal positions don't match for non-pk columns
+ }
+ else {
+ fail(parentTableColumnsMetadata.getColumnName(columnIndex) + " of base table " + parentTableColumnValue + " does not match view "+viewColumnValue) ;
}
}
}
+ parentTableColumnsRs.next();
}
}
}
- assertFalse(getSystemCatalogEntriesForTable(conn, tableName, ""), rs.next());
+ assertFalse(getSystemCatalogEntriesForTable(conn, tableName, ""), viewColumnsRs.next());
}
private String getSystemCatalogEntriesForTable(Connection conn, String tableName, String message) throws Exception {
@@ -2207,7 +2384,13 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
conn.createStatement().execute(dropColumn);
String alterBaseTable = "ALTER TABLE " + baseTable + " ADD V3 VARCHAR";
- conn.createStatement().execute(alterBaseTable);
+ try {
+ conn.createStatement().execute(alterBaseTable);
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals("Unexpected exception", CANNOT_MUTATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
// Column V3 shouldn't have propagated to the divorced view.
String sql = "SELECT V3 FROM " + viewName;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c9a6b8c/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index 1fc1d7f..b27beb4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -39,6 +39,7 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_ARRAY_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_CONSTANT_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IS_VIEW_REFERENCED_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.JAR_PATH_BYTES;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.KEY_SEQ_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.LINK_TYPE_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MAX_VALUE_BYTES;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MIN_VALUE_BYTES;
@@ -1580,8 +1581,18 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
return null; // impossible
}
}
+
+ private boolean isValidLengthOrScale(Integer viewColVal, Cell cell) {
+ Integer baseColValue = cell.getValueArray()==null ? null :
+ PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
+ if ( (baseColValue!=null && viewColVal!=null && baseColValue<viewColVal) || // if the base column has a scale/length less then the view column
+ (viewColVal==null && baseColValue!=null)) { // or if the view column has no scale/length, but the base column has a scale/length
+ return false;
+ }
+ return true;
+ }
- private void addRowsToChildViews(List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
+ private MetaDataMutationResult addRowsToChildViews(List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName,
List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, TableViewFinderResult childViewsResult,
Region region, List<RowLock> locks) throws IOException, SQLException {
for (Result viewResult : childViewsResult.getResults()) {
@@ -1597,18 +1608,28 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
if (view.getBaseColumnCount() == QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT) {
// if a view has divorced itself from the base table, we don't allow schema changes
// to be propagated to it.
- return;
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
}
- int deltaNumberOfColumns = 0;
+ int numColsAddedToBaseTable = 0;
+ int numColsAddedToView = 0;
short deltaNumPkColsSoFar = 0;
+ PColumn existingViewColumn = null;
for (Mutation m : tableMetadata) {
byte[][] rkmd = new byte[5][];
int pkCount = getVarChars(m.getRow(), rkmd);
if (m instanceof Put && pkCount > COLUMN_NAME_INDEX
&& Bytes.compareTo(schemaName, rkmd[SCHEMA_NAME_INDEX]) == 0
&& Bytes.compareTo(tableName, rkmd[TABLE_NAME_INDEX]) == 0) {
+ try {
+ // Maybe deserving of a new SchemaUtil.getColumnByName(byte[] familyName, String columnName) function
+ String columnName = Bytes.toString(rkmd[COLUMN_NAME_INDEX]);
+ existingViewColumn = rkmd[FAMILY_NAME_INDEX] == null
+ ? view.getPKColumn(columnName)
+ : view.getColumnFamily(rkmd[FAMILY_NAME_INDEX]).getColumn(columnName);
+ } catch (ColumnNotFoundException e) {
+ } // Ignore - means column family or column name don't exist
+
Put p = (Put)m;
-
byte[] columnKey = ByteUtil.concat(viewKey, QueryConstants.SEPARATOR_BYTE_ARRAY, rkmd[COLUMN_NAME_INDEX]);
if (rkmd[FAMILY_NAME_INDEX] != null) {
columnKey = ByteUtil.concat(columnKey, QueryConstants.SEPARATOR_BYTE_ARRAY, rkmd[FAMILY_NAME_INDEX]);
@@ -1619,7 +1640,70 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
CellUtil.cloneQualifier(cell), cell.getTimestamp(), cell.getTypeByte(),
CellUtil.cloneValue(cell)));
}
- deltaNumberOfColumns++;
+
+ // if there is already a view column with the same name as the base table column we are trying to add
+ if (existingViewColumn!=null) {
+ List<Cell> dataTypes = viewColumnDefinitionPut
+ .get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+ PhoenixDatabaseMetaData.DATA_TYPE_BYTES);
+ if (dataTypes != null && dataTypes.size() > 0) {
+ Cell cell = dataTypes.get(0);
+ int typeId = PInteger.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
+ PDataType dataType = PDataType.fromTypeId(typeId);
+ if (!existingViewColumn.getDataType().equals(dataType)) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
+ }
+ }
+ if (rkmd[FAMILY_NAME_INDEX] == null && rkmd[COLUMN_NAME_INDEX] != null) {
+ List<Cell> keySeqCells = viewColumnDefinitionPut.get(
+ PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+ PhoenixDatabaseMetaData.KEY_SEQ_BYTES);
+ if (keySeqCells != null && keySeqCells.size() > 0) {
+ Cell cell = keySeqCells.get(0);
+ int keySeq = PSmallint.INSTANCE.getCodec().decodeInt(cell.getValueArray(), cell.getValueOffset(), SortOrder.getDefault());
+ int pkPosition = SchemaUtil.getPKPosition(view, existingViewColumn)+1;
+ if (pkPosition!=keySeq) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
+ }
+ }
+ }
+ // if there is an existing view column that matches the column being added to the base table and if the column being added has a null
+ // scale or maxLength, we need to explicity do a put to set the scale or maxLength to null (in case the view column has the scale or
+ // max length set)
+ List<Cell> columnSizes = viewColumnDefinitionPut.get(
+ PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+ PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES);
+ if (columnSizes != null && columnSizes.size() > 0) {
+ Cell cell = columnSizes.get(0);
+ if (!isValidLengthOrScale(existingViewColumn.getMaxLength(),cell)) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
+ }
+ }
+ else if (existingViewColumn.getMaxLength()!=null) {
+ viewColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+ PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES, null);
+ }
+ List<Cell> decimalDigits = viewColumnDefinitionPut.get(
+ PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+ PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES);
+ if (decimalDigits != null && decimalDigits.size() > 0) {
+ Cell cell = decimalDigits.get(0);
+ if (!isValidLengthOrScale(existingViewColumn.getScale(),cell)) {
+ return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
+ }
+ }
+ else if (existingViewColumn.getScale()!=null) {
+ viewColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
+ PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES, null);
+ }
+ }
+ else {
+ // if we are adding a column that already exists in the view, no need to updates the base table or view table column count
+ numColsAddedToView++;
+ }
+
+
+ numColsAddedToBaseTable++;
mutationsForAddingColumnsToViews.add(viewColumnDefinitionPut);
if (rkmd[FAMILY_NAME_INDEX] == null && rkmd[COLUMN_NAME_INDEX] != null) {
/*
@@ -1743,9 +1827,9 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
Put viewHeaderRowPut = new Put(viewKey, clientTimeStamp);
byte[] baseColumnCountPtr = new byte[PInteger.INSTANCE.getByteSize()];
- PInteger.INSTANCE.getCodec().encodeInt(oldBaseColumnCount + deltaNumberOfColumns, baseColumnCountPtr, 0);
+ PInteger.INSTANCE.getCodec().encodeInt(oldBaseColumnCount + numColsAddedToBaseTable, baseColumnCountPtr, 0);
byte[] columnCountPtr = new byte[PInteger.INSTANCE.getByteSize()];
- PInteger.INSTANCE.getCodec().encodeInt(view.getColumns().size() + deltaNumberOfColumns, columnCountPtr, 0);
+ PInteger.INSTANCE.getCodec().encodeInt(view.getColumns().size() + numColsAddedToView, columnCountPtr, 0);
byte[] viewSequencePtr = new byte[PLong.INSTANCE.getByteSize()];
PLong.INSTANCE.getCodec().encodeLong(view.getSequenceNumber() + 1, viewSequencePtr, 0);
viewHeaderRowPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
@@ -1759,7 +1843,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
// Update positions of view columns
for (PColumn column : view.getColumns()) {
if (column.getPosition() >= oldBaseColumnCount) {
- int newPosition = column.getPosition() + deltaNumberOfColumns + 1;
+ int newPosition = column.getPosition() + numColsAddedToView + 1;
byte[] k = ByteUtil.concat(viewKey, QueryConstants.SEPARATOR_BYTE_ARRAY, column.getName()
.getBytes());
@@ -1777,6 +1861,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
}
invalidateList.add(new ImmutableBytesPtr(viewKey));
}
+ return null;
}
private byte[] getViewIndexHeaderRowKey(PTable index) {
@@ -1820,9 +1905,12 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
EnvironmentEdgeManager.currentTimeMillis(), null);
} else {
mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getResults().size() * tableMetaData.size());
- addRowsToChildViews(tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
+ MetaDataMutationResult mutationResult = addRowsToChildViews(tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp,
childViewsResult, region, locks);
- }
+ // return if we were not able to add the column successfully
+ if (mutationResult!=null)
+ return mutationResult;
+ }
}
}
for (Mutation m : tableMetaData) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c9a6b8c/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 f24da44..8a1c14b 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
@@ -2204,10 +2204,10 @@ public class MetaDataClient {
String familyName = null;
String msg = null;
// TODO: better to return error code
- if (result.getColumnName() != null) {
+ if (result.getColumnName() != null && result.getColumnName() != null) {
familyName = result.getFamilyName() == null ? null : Bytes.toString(result.getFamilyName());
columnName = Bytes.toString(result.getColumnName());
- msg = "Cannot drop column referenced by VIEW";
+ msg = "Cannot add/drop column referenced by VIEW";
}
throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_MUTATE_TABLE)
.setSchemaName(schemaName).setTableName(tableName).setFamilyName(familyName).setColumnName(columnName).setMessage(msg).build().buildException();
[09/50] [abbrv] phoenix git commit: PHOENIX-2025 - Phoenix-core's
hbase-default.xml prevents HBaseTestingUtility from starting up in client
apps (Thomas D'Silva)
Posted by ma...@apache.org.
PHOENIX-2025 - Phoenix-core's hbase-default.xml prevents HBaseTestingUtility from starting up in client apps (Thomas D'Silva)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/973bccb7
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/973bccb7
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/973bccb7
Branch: refs/heads/calcite
Commit: 973bccb7019bfb0c15a9fd5259d7b01f37859b52
Parents: dee7a02
Author: ravimagham <ra...@apache.org>
Authored: Tue Jul 7 22:10:59 2015 -0700
Committer: ravimagham <ra...@apache.org>
Committed: Tue Jul 7 22:10:59 2015 -0700
----------------------------------------------------------------------
.../java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java | 4 ++--
.../phoenix/mapreduce/util/PhoenixConfigurationUtil.java | 6 ++++--
2 files changed, 6 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/973bccb7/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java
index 000ce59..b4724d8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/ConnectionUtil.java
@@ -88,9 +88,9 @@ public class ConnectionUtil {
* @param clientPort a ZooKeeper client port
* @return a Phoenix connection to the given connection string
*/
- private static Connection getConnection(final String quorum, final int clientPort, Properties props) throws SQLException {
+ private static Connection getConnection(final String quorum, final Integer clientPort, Properties props) throws SQLException {
Preconditions.checkNotNull(quorum);
- return DriverManager.getConnection(QueryUtil.getUrl(quorum, clientPort), props);
+ return DriverManager.getConnection(clientPort!=null? QueryUtil.getUrl(quorum, clientPort) : QueryUtil.getUrl(quorum), props);
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/973bccb7/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
index bba96ac..e26f988 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/util/PhoenixConfigurationUtil.java
@@ -27,6 +27,7 @@ import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
@@ -371,9 +372,10 @@ public final class PhoenixConfigurationUtil {
* @param configuration
* @return
*/
- public static int getClientPort(final Configuration configuration) {
+ public static Integer getClientPort(final Configuration configuration) {
Preconditions.checkNotNull(configuration);
- return Integer.parseInt(configuration.get(HBASE_ZOOKEEPER_CLIENT_PORT));
+ String clientPortString = configuration.get(HBASE_ZOOKEEPER_CLIENT_PORT);
+ return clientPortString==null ? null : Integer.parseInt(clientPortString);
}
public static void loadHBaseConfiguration(Job job) throws IOException {
[12/50] [abbrv] phoenix git commit: PHOENIX-2096 Tweak criteria for
when round robin iterator is used
Posted by ma...@apache.org.
PHOENIX-2096 Tweak criteria for when round robin iterator is used
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/61f1900d
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/61f1900d
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/61f1900d
Branch: refs/heads/calcite
Commit: 61f1900ddec5eb5c06245c999711e1fd0c67af53
Parents: 69e55df
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Jul 2 09:48:42 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Wed Jul 8 11:57:40 2015 -0700
----------------------------------------------------------------------
.../apache/phoenix/end2end/ReverseScanIT.java | 29 ++++++++++++++++----
.../org/apache/phoenix/execute/ScanPlan.java | 4 +--
.../java/org/apache/phoenix/util/ScanUtil.java | 7 ++---
3 files changed, 28 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/61f1900d/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java
index 5481d80..eca183b 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java
@@ -19,6 +19,9 @@ package org.apache.phoenix.end2end;
import static org.apache.phoenix.util.TestUtil.ROW2;
import static org.apache.phoenix.util.TestUtil.ROW3;
+import static org.apache.phoenix.util.TestUtil.ROW4;
+import static org.apache.phoenix.util.TestUtil.ROW5;
+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;
@@ -31,6 +34,7 @@ import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
+import java.sql.Statement;
import java.util.Map;
import java.util.Properties;
@@ -39,6 +43,7 @@ import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
import org.apache.phoenix.util.ReadOnlyProps;
import org.apache.phoenix.util.TestUtil;
import org.junit.BeforeClass;
@@ -81,11 +86,11 @@ public class ReverseScanIT extends BaseHBaseManagedTimeIT {
initATableValues(tenantId, getSplitsAtRowKeys(tenantId), getUrl());
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
- String query = "SELECT entity_id FROM aTable WHERE entity_id >= ? ORDER BY organization_id DESC, entity_id DESC";
+ String query = "SELECT entity_id FROM aTable WHERE entity_id >= '" + ROW3 + "' ORDER BY organization_id DESC, entity_id DESC";
try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, ROW7);
- ResultSet rs = statement.executeQuery();
+ Statement stmt = conn.createStatement();
+ stmt.setFetchSize(2);
+ ResultSet rs = stmt.executeQuery(query);
assertTrue (rs.next());
assertEquals(ROW9,rs.getString(1));
@@ -93,10 +98,24 @@ public class ReverseScanIT extends BaseHBaseManagedTimeIT {
assertEquals(ROW8,rs.getString(1));
assertTrue (rs.next());
assertEquals(ROW7,rs.getString(1));
+ assertTrue (rs.next());
+ assertEquals(ROW6,rs.getString(1));
+ assertTrue (rs.next());
+ assertEquals(ROW5,rs.getString(1));
+ assertTrue (rs.next());
+ assertEquals(ROW4,rs.getString(1));
+ assertTrue (rs.next());
+ assertEquals(ROW3,rs.getString(1));
assertFalse(rs.next());
- statement = conn.prepareStatement("SELECT entity_id FROM aTable WHERE organization_id = ? AND entity_id >= ? ORDER BY organization_id DESC, entity_id DESC");
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertEquals(
+ "CLIENT PARALLEL 1-WAY REVERSE FULL SCAN OVER ATABLE\n" +
+ " SERVER FILTER BY FIRST KEY ONLY AND ENTITY_ID >= '00A323122312312'",
+ QueryUtil.getExplainPlan(rs));
+
+ PreparedStatement statement = conn.prepareStatement("SELECT entity_id FROM aTable WHERE organization_id = ? AND entity_id >= ? ORDER BY organization_id DESC, entity_id DESC");
statement.setString(1, tenantId);
statement.setString(2, ROW7);
rs = statement.executeQuery();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/61f1900d/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
index b9dd2f2..fd9f8ad 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
@@ -18,8 +18,6 @@
package org.apache.phoenix.execute;
-import static org.apache.phoenix.util.ScanUtil.shouldRowsBeInRowKeyOrder;
-
import java.sql.SQLException;
import java.util.List;
@@ -187,7 +185,7 @@ public class ScanPlan extends BaseQueryPlan {
if (isOrdered) {
scanner = new MergeSortTopNResultIterator(iterators, limit, orderBy.getOrderByExpressions());
} else {
- if ((isSalted || table.getIndexType() == IndexType.LOCAL) && shouldRowsBeInRowKeyOrder(orderBy, context)) {
+ if ((isSalted || table.getIndexType() == IndexType.LOCAL) && ScanUtil.forceRowKeyOrder(context)) {
scanner = new MergeSortRowKeyResultIterator(iterators, isSalted ? SaltingUtil.NUM_SALTING_BYTES : 0, orderBy == OrderBy.REV_ROW_KEY_ORDER_BY);
} else if (useRoundRobinIterator()) {
scanner = new RoundRobinResultIterator(iterators, this);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/61f1900d/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
index a1473ef..3dff972 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
@@ -672,12 +672,11 @@ public class ScanUtil {
* not even row key order. Also no point doing round robin of scanners if fetch size
* is 1.
*/
- return fetchSize > 1 && !shouldRowsBeInRowKeyOrder(orderBy, context) && orderBy.getOrderByExpressions().isEmpty();
+ return fetchSize > 1 && !forceRowKeyOrder(context) && (orderBy.getOrderByExpressions().isEmpty() && orderBy != FWD_ROW_KEY_ORDER_BY && orderBy != REV_ROW_KEY_ORDER_BY);
}
- public static boolean shouldRowsBeInRowKeyOrder(OrderBy orderBy, StatementContext context) {
- boolean forceRowKeyOrder = context.getConnection().getQueryServices().getProps()
+ public static boolean forceRowKeyOrder(StatementContext context) {
+ return context.getConnection().getQueryServices().getProps()
.getBoolean(QueryServices.FORCE_ROW_KEY_ORDER_ATTRIB, QueryServicesOptions.DEFAULT_FORCE_ROW_KEY_ORDER);
- return forceRowKeyOrder || orderBy == FWD_ROW_KEY_ORDER_BY || orderBy == REV_ROW_KEY_ORDER_BY;
}
}
\ No newline at end of file
[35/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns
Posted by ma...@apache.org.
PHOENIX-2067 Sort order incorrect for variable length DESC columns
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/2620a80c
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/2620a80c
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/2620a80c
Branch: refs/heads/calcite
Commit: 2620a80c1e35c0d214f06a1b16e99da5415a1a2c
Parents: 01b4f60
Author: James Taylor <jt...@salesforce.com>
Authored: Mon Jul 13 11:17:37 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Tue Jul 14 10:55:27 2015 -0700
----------------------------------------------------------------------
dev/eclipse_prefs_phoenix.epf | 2 +-
.../org/apache/phoenix/end2end/ArrayIT.java | 59 +
.../org/apache/phoenix/end2end/IsNullIT.java | 52 +-
.../apache/phoenix/end2end/LpadFunctionIT.java | 24 +
.../apache/phoenix/end2end/ReverseScanIT.java | 30 +
.../phoenix/end2end/RowValueConstructorIT.java | 7 +-
.../apache/phoenix/end2end/SortOrderFIT.java | 563 -----
.../org/apache/phoenix/end2end/SortOrderIT.java | 572 +++++
.../apache/phoenix/compile/FromCompiler.java | 3 +-
.../apache/phoenix/compile/JoinCompiler.java | 8 +-
.../apache/phoenix/compile/OrderByCompiler.java | 4 +-
.../phoenix/compile/OrderPreservingTracker.java | 7 +-
.../org/apache/phoenix/compile/ScanRanges.java | 5 +-
.../compile/TupleProjectionCompiler.java | 4 +-
.../apache/phoenix/compile/UnionCompiler.java | 5 +-
.../apache/phoenix/compile/UpsertCompiler.java | 16 +-
.../apache/phoenix/compile/WhereOptimizer.java | 53 +-
.../coprocessor/BaseScannerRegionObserver.java | 2 +
.../coprocessor/MetaDataEndpointImpl.java | 73 +-
.../UngroupedAggregateRegionObserver.java | 108 +-
.../coprocessor/generated/PTableProtos.java | 105 +-
.../phoenix/exception/SQLExceptionCode.java | 1 +
.../apache/phoenix/execute/BaseQueryPlan.java | 14 +-
.../DescVarLengthFastByteComparisons.java | 219 ++
.../expression/ArrayConstructorExpression.java | 2 +-
.../phoenix/expression/OrderByExpression.java | 13 +-
.../RowValueConstructorExpression.java | 8 +-
.../function/ArrayConcatFunction.java | 11 +-
.../function/ArrayModifierFunction.java | 3 +-
.../expression/function/LpadFunction.java | 8 +-
.../expression/util/regex/JONIPattern.java | 5 +-
.../apache/phoenix/filter/SkipScanFilter.java | 3 +-
.../apache/phoenix/index/IndexMaintainer.java | 127 +-
.../phoenix/iterate/BaseResultIterators.java | 109 +-
.../phoenix/iterate/OrderedResultIterator.java | 52 +-
.../apache/phoenix/jdbc/PhoenixConnection.java | 29 +-
.../query/ConnectionQueryServicesImpl.java | 17 +-
.../java/org/apache/phoenix/query/KeyRange.java | 14 -
.../apache/phoenix/query/QueryConstants.java | 3 +
.../apache/phoenix/schema/DelegateTable.java | 5 +
.../apache/phoenix/schema/MetaDataClient.java | 31 +-
.../java/org/apache/phoenix/schema/PTable.java | 9 +
.../org/apache/phoenix/schema/PTableImpl.java | 78 +-
.../org/apache/phoenix/schema/RowKeySchema.java | 44 +-
.../phoenix/schema/RowKeyValueAccessor.java | 12 +-
.../org/apache/phoenix/schema/ValueSchema.java | 30 +-
.../phoenix/schema/stats/StatisticsUtil.java | 4 +-
.../phoenix/schema/types/PArrayDataType.java | 682 +++---
.../phoenix/schema/types/PBinaryArray.java | 122 +-
.../phoenix/schema/types/PBooleanArray.java | 112 +-
.../apache/phoenix/schema/types/PCharArray.java | 128 +-
.../apache/phoenix/schema/types/PDataType.java | 2037 +++++++++---------
.../apache/phoenix/schema/types/PDateArray.java | 131 +-
.../phoenix/schema/types/PDecimalArray.java | 126 +-
.../phoenix/schema/types/PDoubleArray.java | 128 +-
.../phoenix/schema/types/PFloatArray.java | 130 +-
.../phoenix/schema/types/PIntegerArray.java | 130 +-
.../apache/phoenix/schema/types/PLongArray.java | 130 +-
.../phoenix/schema/types/PSmallintArray.java | 130 +-
.../apache/phoenix/schema/types/PTimeArray.java | 133 +-
.../phoenix/schema/types/PTimestampArray.java | 132 +-
.../phoenix/schema/types/PTinyintArray.java | 130 +-
.../schema/types/PUnsignedDateArray.java | 128 +-
.../schema/types/PUnsignedDoubleArray.java | 136 +-
.../schema/types/PUnsignedFloatArray.java | 130 +-
.../phoenix/schema/types/PUnsignedIntArray.java | 130 +-
.../schema/types/PUnsignedLongArray.java | 130 +-
.../schema/types/PUnsignedSmallintArray.java | 132 +-
.../schema/types/PUnsignedTimeArray.java | 132 +-
.../schema/types/PUnsignedTimestampArray.java | 134 +-
.../schema/types/PUnsignedTinyintArray.java | 132 +-
.../phoenix/schema/types/PVarbinaryArray.java | 130 +-
.../phoenix/schema/types/PVarcharArray.java | 130 +-
.../java/org/apache/phoenix/util/ByteUtil.java | 12 +-
.../org/apache/phoenix/util/MetaDataUtil.java | 2 +-
.../org/apache/phoenix/util/PhoenixRuntime.java | 154 +-
.../java/org/apache/phoenix/util/ScanUtil.java | 15 +-
.../org/apache/phoenix/util/SchemaUtil.java | 23 +
.../java/org/apache/phoenix/util/TupleUtil.java | 7 +-
.../org/apache/phoenix/util/UpgradeUtil.java | 301 +++
.../phoenix/compile/QueryCompilerTest.java | 35 +-
.../org/apache/phoenix/query/OrderByTest.java | 84 +
.../phoenix/schema/types/PDataTypeTest.java | 12 +
phoenix-protocol/src/main/PTable.proto | 1 +
84 files changed, 4997 insertions(+), 4027 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/dev/eclipse_prefs_phoenix.epf
----------------------------------------------------------------------
diff --git a/dev/eclipse_prefs_phoenix.epf b/dev/eclipse_prefs_phoenix.epf
index a218c97..65881ef 100644
--- a/dev/eclipse_prefs_phoenix.epf
+++ b/dev/eclipse_prefs_phoenix.epf
@@ -512,7 +512,7 @@ file_export_version=3.0
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/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 27887e4..89997f4 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
@@ -1980,4 +1980,63 @@ public class ArrayIT extends BaseClientManagedTimeIT {
assertEquals(arr, rs.getArray(1));
rs.next();
}
+
+ @Test
+ public void testPKWithDescArray() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+ long ts = nextTimestamp();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
+ conn = DriverManager.getConnection(getUrl(), props);
+ conn.createStatement()
+ .execute(
+ "CREATE TABLE t ( a VARCHAR ARRAY PRIMARY KEY DESC)\n");
+ conn.close();
+
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO t 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();
+
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40));
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT a FROM t 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();
+
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 50));
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO t VALUES(?)");
+ Array a3 = conn.createArrayOf("VARCHAR", new String[] { "a", "b" });
+ stmt.setArray(1, a3);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 60));
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT a FROM t 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();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/it/java/org/apache/phoenix/end2end/IsNullIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IsNullIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IsNullIT.java
index 9c60914..fb49378 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IsNullIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IsNullIT.java
@@ -19,26 +19,22 @@ package org.apache.phoenix.end2end;
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.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
-import java.util.Properties;
-import org.apache.phoenix.util.PhoenixRuntime;
import org.junit.Test;
-public class IsNullIT extends BaseClientManagedTimeIT {
+public class IsNullIT extends BaseHBaseManagedTimeIT {
@Test
public void testIsNullInPk() throws Exception {
- long ts = nextTimestamp();
- ensureTableCreated(getUrl(),"IntIntKeyTest",null, ts-2);
- Properties props = new Properties();
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 1)); // Execute at timestamp 1
- Connection conn = DriverManager.getConnection(getUrl(), props);
+ ensureTableCreated(getUrl(),"IntIntKeyTest");
+ Connection conn = DriverManager.getConnection(getUrl());
String upsert = "UPSERT INTO IntIntKeyTest VALUES(4,2)";
PreparedStatement upsertStmt = conn.prepareStatement(upsert);
int rowsInserted = upsertStmt.executeUpdate();
@@ -48,10 +44,7 @@ public class IsNullIT extends BaseClientManagedTimeIT {
rowsInserted = upsertStmt.executeUpdate();
assertEquals(1, rowsInserted);
conn.commit();
- conn.close();
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at timestamp 1
- conn = DriverManager.getConnection(getUrl(), props);
String select = "SELECT i/j FROM IntIntKeyTest WHERE j IS NULL";
ResultSet rs;
rs = conn.createStatement().executeQuery(select);
@@ -67,23 +60,38 @@ public class IsNullIT extends BaseClientManagedTimeIT {
}
@Test
+ public void testIsNullWithLastPKColDesc() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE T(k1 VARCHAR NOT NULL, k2 VARCHAR, k3 VARCHAR, CONSTRAINT pk PRIMARY KEY (k1, k2, k3 DESC))");
+ conn.createStatement().execute("UPSERT INTO T VALUES ('a')");
+ conn.createStatement().execute("UPSERT INTO T VALUES ('b')");
+ conn.createStatement().execute("UPSERT INTO T VALUES ('b',null,'c')");
+ conn.createStatement().execute("UPSERT INTO T VALUES ('ba', null, 'd')");
+ conn.commit();
+
+ ResultSet rs = conn.createStatement().executeQuery("SELECT k1,k2,k3 FROM T WHERE k1='b' AND k2 IS NULL");
+ assertTrue(rs.next());
+ assertEquals("b",rs.getString(1));
+ assertNull(rs.getString(2));
+ assertNull(rs.getString(3));
+
+ assertTrue(rs.next());
+ assertEquals("b",rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals("c",rs.getString(3));
+
+ assertFalse(rs.next());
+ conn.close();
+ }
+
+ @Test
public void testIsNullInCompositeKey() throws Exception {
- long ts = nextTimestamp();
- Properties props = new Properties();
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 10));
- Connection conn = DriverManager.getConnection(getUrl(), props);
+ Connection conn = DriverManager.getConnection(getUrl());
conn.createStatement().execute("CREATE TABLE T(k1 VARCHAR, k2 VARCHAR, CONSTRAINT pk PRIMARY KEY (k1,k2))");
- conn.close();
-
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 20));
- conn = DriverManager.getConnection(getUrl(), props);
conn.createStatement().execute("UPSERT INTO T VALUES (null,'a')");
conn.createStatement().execute("UPSERT INTO T VALUES ('a','a')");
conn.commit();
- conn.close();
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
- conn = DriverManager.getConnection(getUrl(), props);
ResultSet rs = conn.createStatement().executeQuery("SELECT count(*) FROM T");
assertTrue(rs.next());
assertEquals(2,rs.getInt(1));
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java
index 0a9bedf..4aa66c2 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LpadFunctionIT.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.phoenix.util.TestUtil;
+import org.junit.Ignore;
import org.junit.Test;
import com.google.common.collect.Lists;
@@ -106,6 +107,29 @@ public class LpadFunctionIT extends BaseHBaseManagedTimeIT {
testLpad(conn, inputList, length, fillStringList, "pk", expectedOutputList);
}
+ @Ignore
+ @Test
+ public void testCharPadding() throws Exception {
+ ResultSet rs;
+ Connection conn = DriverManager.getConnection(getUrl());
+
+ conn.createStatement().execute("CREATE TABLE tdesc (k CHAR(3) PRIMARY KEY DESC)");
+ conn.createStatement().execute("UPSERT INTO tdesc VALUES('a')");
+ conn.commit();
+ rs = conn.createStatement().executeQuery("SELECT * FROM tdesc");
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("CREATE TABLE t (k CHAR(3) PRIMARY KEY)");
+ conn.createStatement().execute("UPSERT INTO t VALUES('a')");
+ conn.commit();
+ rs = conn.createStatement().executeQuery("SELECT * FROM t");
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertFalse(rs.next());
+ }
+
@Test
public void testNullInputStringSB() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java
index eca183b..35a8025 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ReverseScanIT.java
@@ -53,6 +53,8 @@ import com.google.common.collect.Maps;
public class ReverseScanIT extends BaseHBaseManagedTimeIT {
+ protected static final String ATABLE_INDEX_NAME = "ATABLE_IDX";
+
@BeforeClass
@Shadower(classBeingShadowed = BaseHBaseManagedTimeIT.class)
public static void doSetup() throws Exception {
@@ -165,4 +167,32 @@ public class ReverseScanIT extends BaseHBaseManagedTimeIT {
}
}
+ @Test
+ public void testReverseScanIndex() throws Exception {
+ String tenantId = getOrganizationId();
+ initATableValues(tenantId, getSplitsAtRowKeys(tenantId), getUrl());
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String ddl = "CREATE INDEX " + ATABLE_INDEX_NAME + " ON aTable (a_integer DESC) INCLUDE ("
+ + " A_STRING, " + " B_STRING, " + " A_DATE)";
+ conn.createStatement().execute(ddl);
+
+ String query =
+ "SELECT a_integer FROM atable where a_integer is not null order by a_integer nulls last limit 1";
+
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs=statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(1,rs.getInt(1));
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertEquals(
+ "CLIENT SERIAL 1-WAY REVERSE RANGE SCAN OVER ATABLE_IDX [not null]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER 1 ROW LIMIT\n" +
+ "CLIENT 1 ROW LIMIT",QueryUtil.getExplainPlan(rs));
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
index b9e50a4..e5cfeb0 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/RowValueConstructorIT.java
@@ -1232,8 +1232,7 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
@Test
public void testForceSkipScan() throws Exception {
String tempTableWithCompositePK = "TEMP_TABLE_COMPOSITE_PK";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
+ Connection conn = nextConnection(getUrl());
try {
conn.createStatement().execute("CREATE TABLE " + tempTableWithCompositePK
+ " (col0 INTEGER NOT NULL, "
@@ -1242,7 +1241,9 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
+ " col3 INTEGER "
+ " CONSTRAINT pk PRIMARY KEY (col0, col1, col2)) "
+ " SALT_BUCKETS=4");
+ conn.close();
+ conn = nextConnection(getUrl());
PreparedStatement upsertStmt = conn.prepareStatement(
"upsert into " + tempTableWithCompositePK + "(col0, col1, col2, col3) " + "values (?, ?, ?, ?)");
for (int i = 0; i < 3; i++) {
@@ -1253,7 +1254,9 @@ public class RowValueConstructorIT extends BaseClientManagedTimeIT {
upsertStmt.execute();
}
conn.commit();
+ conn.close();
+ conn = nextConnection(getUrl());
String query = "SELECT * FROM " + tempTableWithCompositePK + " WHERE (col0, col1) in ((2, 3), (3, 4), (4, 5))";
PreparedStatement statement = conn.prepareStatement(query);
ResultSet rs = statement.executeQuery();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderFIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderFIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderFIT.java
deleted file mode 100644
index 9fb7ea3..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderFIT.java
+++ /dev/null
@@ -1,563 +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 java.math.BigDecimal;
-import java.math.BigInteger;
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.phoenix.util.PropertiesUtil;
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.google.common.collect.Lists;
-
-/**
- * @since 1.2
- */
-
-
-public class SortOrderFIT extends BaseHBaseManagedTimeIT {
-
- private static final String TABLE = "DescColumnSortOrderTest";
-
- @Test
- public void noOrder() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (pk VARCHAR NOT NULL PRIMARY KEY)";
- runQueryTest(ddl, "pk", new Object[][]{{"a"}, {"b"}, {"c"}}, new Object[][]{{"a"}, {"b"}, {"c"}});
- }
-
- @Test
- public void noOrderCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid, code))";
- Object[][] rows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
- runQueryTest(ddl, upsert("oid", "code"), rows, rows);
- }
-
- @Test
- public void ascOrderInlinePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (pk VARCHAR NOT NULL PRIMARY KEY ASC)";
- runQueryTest(ddl, "pk", new Object[][]{{"a"}, {"b"}, {"c"}}, new Object[][]{{"a"}, {"b"}, {"c"}});
- }
-
- @Test
- public void ascOrderCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid ASC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
- Object[][] expectedRows = new Object[][]{{"o1", 3}, {"o1", 2}, {"o1", 1}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows);
- }
-
- @Test
- public void descOrderInlinePK() throws Exception {
- for (String type : new String[]{"CHAR(2)", "VARCHAR"}) {
- String ddl = "CREATE TABLE " + TABLE + " (pk ${type} NOT NULL PRIMARY KEY DESC)".replace("${type}", type);
- runQueryTest(ddl, "pk", new Object[][]{{"aa"}, {"bb"}, {"cc"}}, new Object[][]{{"cc"}, {"bb"}, {"aa"}});
- }
- }
-
- @Test
- public void descOrderCompositePK1() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
- Object[][] expectedRows = new Object[][]{{"o3", 3}, {"o2", 2}, {"o1", 1}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows);
- }
-
- @Test
- public void descOrderCompositePK2() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
- Object[][] expectedRows = new Object[][]{{"o1", 3}, {"o1", 2}, {"o1", 1}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows);
- }
-
- @Test
- public void equalityDescInlinePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (pk VARCHAR NOT NULL PRIMARY KEY DESC)";
- runQueryTest(ddl, upsert("pk"), new Object[][]{{"a"}, {"b"}, {"c"}}, new Object[][]{{"b"}}, new WhereCondition("pk", "=", "'b'"));
- }
-
- @Test
- public void equalityDescCompositePK1() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"o2", 2}}, new WhereCondition("oid", "=", "'o2'"));
- }
-
- @Test
- public void equalityDescCompositePK2() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"o1", 2}}, new WhereCondition("code", "=", "2"));
- }
-
- @Test
- public void inDescCompositePK1() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"o1", 2}}, new WhereCondition("code", "IN", "(2)"));
- }
-
- @Test
- public void inDescCompositePK2() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"o2", 2}}, new WhereCondition("oid", "IN", "('o2')"));
- }
-
- @Test
- public void likeDescCompositePK1() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"a1", 1}, {"b2", 2}, {"c3", 3}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"b2", 2}}, new WhereCondition("oid", "LIKE", "('b%')"));
- }
-
- @Test
- public void likeDescCompositePK2() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code CHAR(2) NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"a1", "11"}, {"b2", "22"}, {"c3", "33"}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"b2", "22"}}, new WhereCondition("code", "LIKE", "('2%')"));
- }
-
- @Test
- public void greaterThanDescCompositePK3() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
- Object[][] expectedRows = new Object[][]{{"o1", 2}, {"o1", 1}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("code", "<", "3"));
- }
-
- @Test
- public void substrDescCompositePK1() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(3) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code ASC))";
- Object[][] insertedRows = new Object[][]{{"ao1", 1}, {"bo2", 2}, {"co3", 3}};
- Object[][] expectedRows = new Object[][]{{"co3", 3}, {"bo2", 2}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("SUBSTR(oid, 3, 1)", ">", "'1'"));
- }
-
- @Test
- public void substrDescCompositePK2() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(4) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code ASC))";
- Object[][] insertedRows = new Object[][]{{"aaaa", 1}, {"bbbb", 2}, {"cccd", 3}};
- Object[][] expectedRows = new Object[][]{{"cccd", 3}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("SUBSTR(oid, 4, 1)", "=", "'d'"));
- }
-
- @Test
- public void lTrimDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid VARCHAR NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{" o1 ", 1}, {" o2", 2}, {" o3", 3}};
- Object[][] expectedRows = new Object[][]{{" o2", 2}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("LTRIM(oid)", "=", "'o2'"));
- }
-
- @Test
- public void lPadDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid VARCHAR NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"aaaa", 1}, {"bbbb", 2}, {"cccc", 3}};
- Object[][] expectedRows = new Object[][]{{"bbbb", 2}};
- runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("LPAD(oid, 8, '123')", "=", "'1231bbbb'"));
- }
-
- @Test
- public void countDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code ASC))";
- Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
- Object[][] expectedRows = new Object[][]{{3l}};
- runQueryTest(ddl, upsert("oid", "code"), select("COUNT(oid)"), insertedRows, expectedRows);
- }
-
- @Test
- public void sumDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL " +
- "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC))";
- Object[][] insertedRows = new Object[][]{{10, bdec(10.2), 21l}, {20, bdec(20.2), 32l}, {30, bdec(30.2), 43l}};
- Object[][] expectedRows = new Object[][]{{60l, bdec(60.6), 96l}};
- runQueryTest(ddl, upsert("n1", "n2", "n3"), select("SUM(n1), SUM(n2), SUM(n3)"), insertedRows, expectedRows);
- }
-
- @Test
- public void avgDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL " +
- "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC))";
- Object[][] insertedRows = new Object[][]{{10, bdec(10.2), 21l}, {20, bdec(20.2), 32l}, {30, bdec(30.2), 43l}};
- Object[][] expectedRows = new Object[][]{{new BigDecimal(bint(2), -1), bdec(20.2), BigDecimal.valueOf(32)}};
- runQueryTest(ddl, upsert("n1", "n2", "n3"), select("AVG(n1), AVG(n2), AVG(n3)"), insertedRows, expectedRows);
- }
-
- @Test
- public void minDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL " +
- "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC))";
- Object[][] insertedRows = new Object[][]{{10, bdec(10.2), 21l}, {20, bdec(20.2), 32l}, {30, bdec(30.2), 43l}};
- Object[][] expectedRows = new Object[][]{{10, bdec(10.2), 21l}};
- runQueryTest(ddl, upsert("n1", "n2", "n3"), select("MIN(n1), MIN(n2), MIN(n3)"), insertedRows, expectedRows);
- }
-
- @Test
- public void maxDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL " +
- "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC))";
- Object[][] insertedRows = new Object[][]{{10, bdec(10.2), 21l}, {20, bdec(20.2), 32l}, {30, bdec(30.2), 43l}};
- Object[][] expectedRows = new Object[][]{{30, bdec(30.2), 43l}};
- runQueryTest(ddl, upsert("n1", "n2", "n3"), select("MAX(n1), MAX(n2), MAX(n3)"), insertedRows, expectedRows);
- }
-
- @Test
- public void havingSumDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (name CHAR(1) NOT NULL, code INTEGER NOT NULL " +
- "constraint pk primary key (name DESC, code DESC))";
- Object[][] insertedRows = new Object[][]{{"a", 10}, {"a", 20}, {"b", 100}};
- Object[][] expectedRows = new Object[][]{{"a", 30l}};
- runQueryTest(ddl, upsert("name", "code"), select("name", "SUM(code)"), insertedRows, expectedRows,
- new HavingCondition("name", "SUM(code) = 30"));
- }
-
- @Test
- public void queryDescDateWithExplicitOrderBy() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (c1 CHAR(1) NOT NULL, c2 CHAR(1) NOT NULL, d1 DATE NOT NULL, c3 CHAR(1) NOT NULL " +
- "constraint pk primary key (c1, c2, d1 DESC, c3))";
- Object[] row1 = {"1", "2", date(10, 11, 2001), "3"};
- Object[] row2 = {"1", "2", date(10, 11, 2003), "3"};
- Object[][] insertedRows = new Object[][]{row1, row2};
- runQueryTest(ddl, upsert("c1", "c2", "d1", "c3"), select("c1, c2, d1", "c3"), insertedRows, new Object[][]{row2, row1},
- null, null, new OrderBy("d1", OrderBy.Direction.DESC));
- }
-
- @Test
- public void additionOnDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL, d1 DATE NOT NULL " +
- "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC, d1 DESC))";
- Object[][] insertedRows = new Object[][]{
- {10, bdec(10.2), 21l, date(1, 10, 2001)}, {20, bdec(20.2), 32l, date(2, 6, 2001)}, {30, bdec(30.2), 43l, date(3, 1, 2001)}};
- Object[][] expectedRows = new Object[][]{
- {31l, bdec(32.2), 46l, date(3, 5, 2001)}, {21l, bdec(22.2), 35l, date(2, 10, 2001)}, {11l, bdec(12.2), 24l, date(1, 14, 2001)}};
- runQueryTest(ddl, upsert("n1", "n2", "n3", "d1"), select("n1+1, n2+2, n3+3", "d1+4"), insertedRows, expectedRows);
- }
-
- @Test
- public void subtractionOnDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL, d1 DATE NOT NULL " +
- "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC, d1 DESC))";
- Object[][] insertedRows = new Object[][]{
- {10, bdec(10.2), 21l, date(1, 10, 2001)}, {20, bdec(20.2), 32l, date(2, 6, 2001)}, {30, bdec(30.2), 43l, date(3, 10, 2001)}};
- Object[][] expectedRows = new Object[][]{
- {29l, bdec(28.2), 40l, date(3, 6, 2001)}, {19l, bdec(18.2), 29l, date(2, 2, 2001)}, {9l, bdec(8.2), 18l, date(1, 6, 2001)}};
- runQueryTest(ddl, upsert("n1", "n2", "n3", "d1"), select("n1-1, n2-2, n3-3", "d1-4"), insertedRows, expectedRows);
- }
-
- @Test
- public void lessThanLeadingDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (id INTEGER NOT NULL, date DATE NOT NULL constraint pk primary key (id DESC, date))";
- Object[][] insertedRows = new Object[][]{{1, date(1, 1, 2012)}, {3, date(1, 1, 2013)}, {2, date(1, 1, 2011)}};
- Object[][] expectedRows = new Object[][]{{1, date(1, 1, 2012)}};
- runQueryTest(ddl, upsert("id", "date"), insertedRows, expectedRows, new WhereCondition("id", "<", "2"));
- }
-
- @Test
- public void lessThanTrailingDescCompositePK() throws Exception {
- String ddl = "CREATE TABLE " + TABLE + " (id INTEGER NOT NULL, date DATE NOT NULL constraint pk primary key (id DESC, date))";
- Object[][] insertedRows = new Object[][]{{1, date(1, 1, 2002)}, {3, date(1, 1, 2003)}, {2, date(1, 1, 2001)}};
- Object[][] expectedRows = new Object[][]{{2, date(1, 1, 2001)}};
- runQueryTest(ddl, upsert("id", "date"), insertedRows, expectedRows, new WhereCondition("date", "<", "TO_DATE('02-02-2001','mm-dd-yyyy')"));
- }
-
- private void runQueryTest(String ddl, String columnName, Object[][] rows, Object[][] expectedRows) throws Exception {
- runQueryTest(ddl, new String[]{columnName}, rows, expectedRows, null);
- }
-
- private void runQueryTest(String ddl, String[] columnNames, Object[][] rows, Object[][] expectedRows) throws Exception {
- runQueryTest(ddl, columnNames, rows, expectedRows, null);
- }
-
- private void runQueryTest(String ddl, String[] columnNames, Object[][] rows, Object[][] expectedRows, WhereCondition condition) throws Exception {
- runQueryTest(ddl, columnNames, columnNames, rows, expectedRows, condition, null, null);
- }
-
- private void runQueryTest(String ddl, String[] columnNames, String[] projections, Object[][] rows, Object[][] expectedRows) throws Exception {
- runQueryTest(ddl, columnNames, projections, rows, expectedRows, null, null, null);
- }
-
- private void runQueryTest(String ddl, String[] columnNames, String[] projections, Object[][] rows, Object[][] expectedRows, HavingCondition havingCondition) throws Exception {
- runQueryTest(ddl, columnNames, projections, rows, expectedRows, null, havingCondition, null);
- }
-
-
- private void runQueryTest(
- String ddl,
- String[] columnNames,
- String[] projections,
- Object[][] rows, Object[][] expectedRows,
- WhereCondition whereCondition,
- HavingCondition havingCondition,
- OrderBy orderBy)
- throws Exception
- {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
-
- try {
-
- conn.setAutoCommit(false);
-
- createTestTable(getUrl(), ddl);
-
- String columns = appendColumns(columnNames);
- String placeholders = appendPlaceholders(columnNames);
- String dml = "UPSERT INTO " + TABLE + " (" + columns + ") VALUES(" + placeholders +")";
- PreparedStatement stmt = conn.prepareStatement(dml);
-
- for (int row = 0; row < rows.length; row++) {
- for (int col = 0; col < rows[row].length; col++) {
- Object value = rows[row][col];
- stmt.setObject(col + 1, value);
- }
- stmt.execute();
- }
- conn.commit();
-
- String selectClause = "SELECT " + appendColumns(projections) + " FROM " + TABLE;
-
- for (WhereCondition whereConditionClause : new WhereCondition[]{whereCondition, WhereCondition.reverse(whereCondition)}) {
- String query = WhereCondition.appendWhere(whereConditionClause, selectClause);
- query = HavingCondition.appendHaving(havingCondition, query);
- query = OrderBy.appendOrderBy(orderBy, query);
- runQuery(conn, query, expectedRows);
- }
-
- if (orderBy != null) {
- orderBy = OrderBy.reverse(orderBy);
- String query = WhereCondition.appendWhere(whereCondition, selectClause);
- query = HavingCondition.appendHaving(havingCondition, query);
- query = OrderBy.appendOrderBy(orderBy, query);
- runQuery(conn, query, reverse(expectedRows));
- }
-
- } finally {
- conn.close();
- }
- }
-
- private String appendColumns(String[] columnNames) {
- String appendedColumns = "";
- for (int i = 0; i < columnNames.length; i++) {
- appendedColumns += columnNames[i];
- if (i < columnNames.length - 1) {
- appendedColumns += ",";
- }
- }
- return appendedColumns;
- }
-
- private String appendPlaceholders(String[] columnNames) {
- String placeholderList = "";
- for (int i = 0; i < columnNames.length; i++) {
- placeholderList += "?";
- if (i < columnNames.length - 1) {
- placeholderList += ",";
- }
- }
- return placeholderList;
- }
-
- private static void runQuery(Connection connection, String query, Object[][] expectedValues) throws Exception {
- PreparedStatement stmt = connection.prepareStatement(query);
-
- ResultSet rs = stmt.executeQuery();
- int rowCounter = 0;
- while (rs.next()) {
- if (rowCounter == expectedValues.length) {
- Assert.assertEquals("Exceeded number of expected rows for query" + query, expectedValues.length, rowCounter+1);
- }
- Object[] cols = new Object[expectedValues[rowCounter].length];
- for (int colCounter = 0; colCounter < expectedValues[rowCounter].length; colCounter++) {
- cols[colCounter] = rs.getObject(colCounter+1);
- }
- Assert.assertArrayEquals("Unexpected result for query " + query, expectedValues[rowCounter], cols);
- rowCounter++;
- }
- Assert.assertEquals("Unexpected number of rows for query " + query, expectedValues.length, rowCounter);
- }
-
- private static Object[][] reverse(Object[][] rows) {
- Object[][] reversedArray = new Object[rows.length][];
- System.arraycopy(rows, 0, reversedArray, 0, rows.length);
- ArrayUtils.reverse(reversedArray);
- return reversedArray;
- }
-
- private static Date date(int month, int day, int year) {
- Calendar cal = new GregorianCalendar();
- cal.set(Calendar.MONTH, month-1);
- cal.set(Calendar.DAY_OF_MONTH, day);
- cal.set(Calendar.YEAR, year);
- cal.set(Calendar.HOUR_OF_DAY, 10);
- cal.set(Calendar.MINUTE, 2);
- cal.set(Calendar.SECOND, 5);
- cal.set(Calendar.MILLISECOND, 101);
- Date d = new Date(cal.getTimeInMillis());
- return d;
- }
-
- private static String[] upsert(String...args) {
- return args;
- }
-
- private static String[] select(String...args) {
- return args;
- }
-
- private static BigDecimal bdec(double d) {
- return BigDecimal.valueOf(d);
- }
-
- private static BigInteger bint(long l) {
- return BigInteger.valueOf(l);
- }
-
- private static class WhereCondition {
- final String lhs;
- final String operator;
- final String rhs;
-
- WhereCondition(String lhs, String operator, String rhs) {
- this.lhs = lhs;
- this.operator = operator;
- this.rhs = rhs;
- }
-
- static WhereCondition reverse(WhereCondition whereCondition) {
-
- if (whereCondition == null) {
- return null;
- }
-
- if (whereCondition.operator.equalsIgnoreCase("IN") || whereCondition.operator.equalsIgnoreCase("LIKE")) {
- return whereCondition;
- } else {
- return new WhereCondition(whereCondition.rhs, whereCondition.getReversedOperator(), whereCondition.lhs);
- }
- }
-
- static String appendWhere(WhereCondition whereCondition, String query) {
- if (whereCondition == null) {
- return query;
- }
- return query + " WHERE " + whereCondition.lhs + " " + whereCondition.operator + " " + whereCondition.rhs;
- }
-
- private String getReversedOperator() {
- if (operator.equals("<")) {
- return ">";
- } else if (operator.equals(">")) {
- return "<";
- }
- return operator;
- }
- }
-
- private static class HavingCondition {
-
- private String groupby;
- private String having;
-
- HavingCondition(String groupby, String having) {
- this.groupby = groupby;
- this.having = having;
- }
-
- static String appendHaving(HavingCondition havingCondition, String query) {
- if (havingCondition == null) {
- return query;
- }
- return query + " GROUP BY " + havingCondition.groupby + " HAVING " + havingCondition.having + " ";
- }
- }
-
- private static class OrderBy {
-
- enum Direction {
-
- ASC, DESC;
-
- Direction reverse() {
- if (this == ASC) {
- return DESC;
- }
- return ASC;
- }
- }
-
- private List<String> columnNames = Lists.newArrayList();
- private List<Direction> directions = Lists.newArrayList();
-
- OrderBy() {
- }
-
- OrderBy(String columnName, Direction orderBy) {
- add(columnName, orderBy);
- }
-
- void add(String columnName, Direction direction) {
- columnNames.add(columnName);
- directions.add(direction);
- }
-
- static OrderBy reverse(OrderBy orderBy) {
-
- if (orderBy == null) {
- return null;
- }
-
- List<Direction> reversedDirections = Lists.newArrayList();
- for (Direction dir : orderBy.directions) {
- reversedDirections.add(dir.reverse());
- }
- OrderBy reversedOrderBy = new OrderBy();
- reversedOrderBy.columnNames = orderBy.columnNames;
- reversedOrderBy.directions = reversedDirections;
- return reversedOrderBy;
- }
-
- static String appendOrderBy(OrderBy orderBy, String query) {
- if (orderBy == null || orderBy.columnNames.isEmpty()) {
- return query;
- }
- query += " ORDER BY ";
- for (int i = 0; i < orderBy.columnNames.size(); i++) {
- query += orderBy.columnNames.get(i) + " " + orderBy.directions.get(i).toString() + " ";
- }
-
- query += " LIMIT 1000 ";
-
- return query;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
new file mode 100644
index 0000000..a03f71e
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortOrderIT.java
@@ -0,0 +1,572 @@
+/*
+ * 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 java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+/**
+ * @since 1.2
+ */
+
+
+public class SortOrderIT extends BaseHBaseManagedTimeIT {
+
+ private static final String TABLE = "DescColumnSortOrderTest";
+
+ @Test
+ public void noOrder() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (pk VARCHAR NOT NULL PRIMARY KEY)";
+ runQueryTest(ddl, "pk", new Object[][]{{"a"}, {"b"}, {"c"}}, new Object[][]{{"a"}, {"b"}, {"c"}});
+ }
+
+ @Test
+ public void noOrderCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid, code))";
+ Object[][] rows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
+ runQueryTest(ddl, upsert("oid", "code"), rows, rows);
+ }
+
+ @Test
+ public void ascOrderInlinePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (pk VARCHAR NOT NULL PRIMARY KEY ASC)";
+ runQueryTest(ddl, "pk", new Object[][]{{"a"}, {"b"}, {"c"}}, new Object[][]{{"a"}, {"b"}, {"c"}});
+ }
+
+ @Test
+ public void ascOrderCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid ASC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
+ Object[][] expectedRows = new Object[][]{{"o1", 3}, {"o1", 2}, {"o1", 1}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void descOrderInlinePK() throws Exception {
+ for (String type : new String[]{"CHAR(2)", "VARCHAR"}) {
+ String ddl = "CREATE TABLE " + TABLE + " (pk ${type} NOT NULL PRIMARY KEY DESC)".replace("${type}", type);
+ runQueryTest(ddl, "pk", new Object[][]{{"aa"}, {"bb"}, {"cc"}}, new Object[][]{{"cc"}, {"bb"}, {"aa"}});
+ }
+ }
+
+ @Test
+ public void descOrderCompositePK1() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
+ Object[][] expectedRows = new Object[][]{{"o3", 3}, {"o2", 2}, {"o1", 1}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void descOrderCompositePK2() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
+ Object[][] expectedRows = new Object[][]{{"o1", 3}, {"o1", 2}, {"o1", 1}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void equalityDescInlinePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (pk VARCHAR NOT NULL PRIMARY KEY DESC)";
+ runQueryTest(ddl, upsert("pk"), new Object[][]{{"a"}, {"b"}, {"c"}}, new Object[][]{{"b"}}, new WhereCondition("pk", "=", "'b'"));
+ }
+
+ @Test
+ public void equalityDescCompositePK1() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"o2", 2}}, new WhereCondition("oid", "=", "'o2'"));
+ }
+
+ @Test
+ public void equalityDescCompositePK2() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"o1", 2}}, new WhereCondition("code", "=", "2"));
+ }
+
+ @Test
+ public void inDescCompositePK1() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"o1", 2}}, new WhereCondition("code", "IN", "(2)"));
+ }
+
+ @Test
+ public void inDescCompositePK2() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"o2", 2}}, new WhereCondition("oid", "IN", "('o2')"));
+ }
+
+ @Test
+ public void likeDescCompositePK1() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"a1", 1}, {"b2", 2}, {"c3", 3}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"b2", 2}}, new WhereCondition("oid", "LIKE", "('b%')"));
+ }
+
+ @Test
+ public void likeDescCompositePK2() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code CHAR(2) NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"a1", "11"}, {"b2", "22"}, {"c3", "33"}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, new Object[][]{{"b2", "22"}}, new WhereCondition("code", "LIKE", "('2%')"));
+ }
+
+ @Test
+ public void greaterThanDescCompositePK3() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o1", 2}, {"o1", 3}};
+ Object[][] expectedRows = new Object[][]{{"o1", 2}, {"o1", 1}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("code", "<", "3"));
+ }
+
+ @Test
+ public void substrDescCompositePK1() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(3) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code ASC))";
+ Object[][] insertedRows = new Object[][]{{"ao1", 1}, {"bo2", 2}, {"co3", 3}};
+ Object[][] expectedRows = new Object[][]{{"co3", 3}, {"bo2", 2}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("SUBSTR(oid, 3, 1)", ">", "'1'"));
+ }
+
+ @Test
+ public void substrDescCompositePK2() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(4) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code ASC))";
+ Object[][] insertedRows = new Object[][]{{"aaaa", 1}, {"bbbb", 2}, {"cccd", 3}};
+ Object[][] expectedRows = new Object[][]{{"cccd", 3}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("SUBSTR(oid, 4, 1)", "=", "'d'"));
+ }
+
+ @Test
+ public void lTrimDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid VARCHAR NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{" o1 ", 1}, {" o2", 2}, {" o3", 3}};
+ Object[][] expectedRows = new Object[][]{{" o2", 2}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("LTRIM(oid)", "=", "'o2'"));
+ }
+
+ @Test
+ public void lPadDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid VARCHAR NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"aaaa", 1}, {"bbbb", 2}, {"cccc", 3}};
+ Object[][] expectedRows = new Object[][]{{"bbbb", 2}};
+ runQueryTest(ddl, upsert("oid", "code"), insertedRows, expectedRows, new WhereCondition("LPAD(oid, 8, '123')", "=", "'1231bbbb'"));
+ }
+
+ @Test
+ public void countDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (oid CHAR(2) NOT NULL, code INTEGER NOT NULL constraint pk primary key (oid DESC, code ASC))";
+ Object[][] insertedRows = new Object[][]{{"o1", 1}, {"o2", 2}, {"o3", 3}};
+ Object[][] expectedRows = new Object[][]{{3l}};
+ runQueryTest(ddl, upsert("oid", "code"), select("COUNT(oid)"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void sumDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL " +
+ "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC))";
+ Object[][] insertedRows = new Object[][]{{10, bdec(10.2), 21l}, {20, bdec(20.2), 32l}, {30, bdec(30.2), 43l}};
+ Object[][] expectedRows = new Object[][]{{60l, bdec(60.6), 96l}};
+ runQueryTest(ddl, upsert("n1", "n2", "n3"), select("SUM(n1), SUM(n2), SUM(n3)"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void avgDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL " +
+ "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC))";
+ Object[][] insertedRows = new Object[][]{{10, bdec(10.2), 21l}, {20, bdec(20.2), 32l}, {30, bdec(30.2), 43l}};
+ Object[][] expectedRows = new Object[][]{{new BigDecimal(bint(2), -1), bdec(20.2), BigDecimal.valueOf(32)}};
+ runQueryTest(ddl, upsert("n1", "n2", "n3"), select("AVG(n1), AVG(n2), AVG(n3)"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void minDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL " +
+ "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC))";
+ Object[][] insertedRows = new Object[][]{{10, bdec(10.2), 21l}, {20, bdec(20.2), 32l}, {30, bdec(30.2), 43l}};
+ Object[][] expectedRows = new Object[][]{{10, bdec(10.2), 21l}};
+ runQueryTest(ddl, upsert("n1", "n2", "n3"), select("MIN(n1), MIN(n2), MIN(n3)"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void maxDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL " +
+ "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC))";
+ Object[][] insertedRows = new Object[][]{{10, bdec(10.2), 21l}, {20, bdec(20.2), 32l}, {30, bdec(30.2), 43l}};
+ Object[][] expectedRows = new Object[][]{{30, bdec(30.2), 43l}};
+ runQueryTest(ddl, upsert("n1", "n2", "n3"), select("MAX(n1), MAX(n2), MAX(n3)"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void havingSumDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (name CHAR(1) NOT NULL, code INTEGER NOT NULL " +
+ "constraint pk primary key (name DESC, code DESC))";
+ Object[][] insertedRows = new Object[][]{{"a", 10}, {"a", 20}, {"b", 100}};
+ Object[][] expectedRows = new Object[][]{{"a", 30l}};
+ runQueryTest(ddl, upsert("name", "code"), select("name", "SUM(code)"), insertedRows, expectedRows,
+ new HavingCondition("name", "SUM(code) = 30"));
+ }
+
+ @Test
+ public void queryDescDateWithExplicitOrderBy() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (c1 CHAR(1) NOT NULL, c2 CHAR(1) NOT NULL, d1 DATE NOT NULL, c3 CHAR(1) NOT NULL " +
+ "constraint pk primary key (c1, c2, d1 DESC, c3))";
+ Object[] row1 = {"1", "2", date(10, 11, 2001), "3"};
+ Object[] row2 = {"1", "2", date(10, 11, 2003), "3"};
+ Object[][] insertedRows = new Object[][]{row1, row2};
+ runQueryTest(ddl, upsert("c1", "c2", "d1", "c3"), select("c1, c2, d1", "c3"), insertedRows, new Object[][]{row2, row1},
+ null, null, new OrderBy("d1", OrderBy.Direction.DESC));
+ }
+
+ @Test
+ public void additionOnDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL, d1 DATE NOT NULL " +
+ "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC, d1 DESC))";
+ Object[][] insertedRows = new Object[][]{
+ {10, bdec(10.2), 21l, date(1, 10, 2001)}, {20, bdec(20.2), 32l, date(2, 6, 2001)}, {30, bdec(30.2), 43l, date(3, 1, 2001)}};
+ Object[][] expectedRows = new Object[][]{
+ {31l, bdec(32.2), 46l, date(3, 5, 2001)}, {21l, bdec(22.2), 35l, date(2, 10, 2001)}, {11l, bdec(12.2), 24l, date(1, 14, 2001)}};
+ runQueryTest(ddl, upsert("n1", "n2", "n3", "d1"), select("n1+1, n2+2, n3+3", "d1+4"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void subtractionOnDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (n1 INTEGER NOT NULL, n2 DECIMAL(10, 2) NOT NULL, n3 BIGINT NOT NULL, d1 DATE NOT NULL " +
+ "constraint pk primary key (n1 DESC, n2 DESC, n3 DESC, d1 DESC))";
+ Object[][] insertedRows = new Object[][]{
+ {10, bdec(10.2), 21l, date(1, 10, 2001)}, {20, bdec(20.2), 32l, date(2, 6, 2001)}, {30, bdec(30.2), 43l, date(3, 10, 2001)}};
+ Object[][] expectedRows = new Object[][]{
+ {29l, bdec(28.2), 40l, date(3, 6, 2001)}, {19l, bdec(18.2), 29l, date(2, 2, 2001)}, {9l, bdec(8.2), 18l, date(1, 6, 2001)}};
+ runQueryTest(ddl, upsert("n1", "n2", "n3", "d1"), select("n1-1, n2-2, n3-3", "d1-4"), insertedRows, expectedRows);
+ }
+
+ @Test
+ public void lessThanLeadingDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (id INTEGER NOT NULL, date DATE NOT NULL constraint pk primary key (id DESC, date))";
+ Object[][] insertedRows = new Object[][]{{1, date(1, 1, 2012)}, {3, date(1, 1, 2013)}, {2, date(1, 1, 2011)}};
+ Object[][] expectedRows = new Object[][]{{1, date(1, 1, 2012)}};
+ runQueryTest(ddl, upsert("id", "date"), insertedRows, expectedRows, new WhereCondition("id", "<", "2"));
+ }
+
+ @Test
+ public void lessThanTrailingDescCompositePK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (id INTEGER NOT NULL, date DATE NOT NULL constraint pk primary key (id DESC, date))";
+ Object[][] insertedRows = new Object[][]{{1, date(1, 1, 2002)}, {3, date(1, 1, 2003)}, {2, date(1, 1, 2001)}};
+ Object[][] expectedRows = new Object[][]{{2, date(1, 1, 2001)}};
+ runQueryTest(ddl, upsert("id", "date"), insertedRows, expectedRows, new WhereCondition("date", "<", "TO_DATE('02-02-2001','mm-dd-yyyy')"));
+ }
+
+ @Test
+ public void descVarLengthPK() throws Exception {
+ String ddl = "CREATE TABLE " + TABLE + " (id VARCHAR PRIMARY KEY DESC)";
+ Object[][] insertedRows = new Object[][]{{"a"}, {"ab"}, {"abc"}};
+ Object[][] expectedRows = new Object[][]{{"abc"}, {"ab"}, {"a"}};
+ runQueryTest(ddl, upsert("id"), select("id"), insertedRows, expectedRows,
+ null, null, new OrderBy("id", OrderBy.Direction.DESC));
+ }
+
+ private void runQueryTest(String ddl, String columnName, Object[][] rows, Object[][] expectedRows) throws Exception {
+ runQueryTest(ddl, new String[]{columnName}, rows, expectedRows, null);
+ }
+
+ private void runQueryTest(String ddl, String[] columnNames, Object[][] rows, Object[][] expectedRows) throws Exception {
+ runQueryTest(ddl, columnNames, rows, expectedRows, null);
+ }
+
+ private void runQueryTest(String ddl, String[] columnNames, Object[][] rows, Object[][] expectedRows, WhereCondition condition) throws Exception {
+ runQueryTest(ddl, columnNames, columnNames, rows, expectedRows, condition, null, null);
+ }
+
+ private void runQueryTest(String ddl, String[] columnNames, String[] projections, Object[][] rows, Object[][] expectedRows) throws Exception {
+ runQueryTest(ddl, columnNames, projections, rows, expectedRows, null, null, null);
+ }
+
+ private void runQueryTest(String ddl, String[] columnNames, String[] projections, Object[][] rows, Object[][] expectedRows, HavingCondition havingCondition) throws Exception {
+ runQueryTest(ddl, columnNames, projections, rows, expectedRows, null, havingCondition, null);
+ }
+
+
+ private void runQueryTest(
+ String ddl,
+ String[] columnNames,
+ String[] projections,
+ Object[][] rows, Object[][] expectedRows,
+ WhereCondition whereCondition,
+ HavingCondition havingCondition,
+ OrderBy orderBy)
+ throws Exception
+ {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+
+ try {
+
+ conn.setAutoCommit(false);
+
+ createTestTable(getUrl(), ddl);
+
+ String columns = appendColumns(columnNames);
+ String placeholders = appendPlaceholders(columnNames);
+ String dml = "UPSERT INTO " + TABLE + " (" + columns + ") VALUES(" + placeholders +")";
+ PreparedStatement stmt = conn.prepareStatement(dml);
+
+ for (int row = 0; row < rows.length; row++) {
+ for (int col = 0; col < rows[row].length; col++) {
+ Object value = rows[row][col];
+ stmt.setObject(col + 1, value);
+ }
+ stmt.execute();
+ }
+ conn.commit();
+
+ String selectClause = "SELECT " + appendColumns(projections) + " FROM " + TABLE;
+
+ for (WhereCondition whereConditionClause : new WhereCondition[]{whereCondition, WhereCondition.reverse(whereCondition)}) {
+ String query = WhereCondition.appendWhere(whereConditionClause, selectClause);
+ query = HavingCondition.appendHaving(havingCondition, query);
+ query = OrderBy.appendOrderBy(orderBy, query);
+ runQuery(conn, query, expectedRows);
+ }
+
+ if (orderBy != null) {
+ orderBy = OrderBy.reverse(orderBy);
+ String query = WhereCondition.appendWhere(whereCondition, selectClause);
+ query = HavingCondition.appendHaving(havingCondition, query);
+ query = OrderBy.appendOrderBy(orderBy, query);
+ runQuery(conn, query, reverse(expectedRows));
+ }
+
+ } finally {
+ conn.close();
+ }
+ }
+
+ private String appendColumns(String[] columnNames) {
+ String appendedColumns = "";
+ for (int i = 0; i < columnNames.length; i++) {
+ appendedColumns += columnNames[i];
+ if (i < columnNames.length - 1) {
+ appendedColumns += ",";
+ }
+ }
+ return appendedColumns;
+ }
+
+ private String appendPlaceholders(String[] columnNames) {
+ String placeholderList = "";
+ for (int i = 0; i < columnNames.length; i++) {
+ placeholderList += "?";
+ if (i < columnNames.length - 1) {
+ placeholderList += ",";
+ }
+ }
+ return placeholderList;
+ }
+
+ private static void runQuery(Connection connection, String query, Object[][] expectedValues) throws Exception {
+ PreparedStatement stmt = connection.prepareStatement(query);
+
+ ResultSet rs = stmt.executeQuery();
+ int rowCounter = 0;
+ while (rs.next()) {
+ if (rowCounter == expectedValues.length) {
+ Assert.assertEquals("Exceeded number of expected rows for query" + query, expectedValues.length, rowCounter+1);
+ }
+ Object[] cols = new Object[expectedValues[rowCounter].length];
+ for (int colCounter = 0; colCounter < expectedValues[rowCounter].length; colCounter++) {
+ cols[colCounter] = rs.getObject(colCounter+1);
+ }
+ Assert.assertArrayEquals("Unexpected result for query " + query, expectedValues[rowCounter], cols);
+ rowCounter++;
+ }
+ Assert.assertEquals("Unexpected number of rows for query " + query, expectedValues.length, rowCounter);
+ }
+
+ private static Object[][] reverse(Object[][] rows) {
+ Object[][] reversedArray = new Object[rows.length][];
+ System.arraycopy(rows, 0, reversedArray, 0, rows.length);
+ ArrayUtils.reverse(reversedArray);
+ return reversedArray;
+ }
+
+ private static Date date(int month, int day, int year) {
+ Calendar cal = new GregorianCalendar();
+ cal.set(Calendar.MONTH, month-1);
+ cal.set(Calendar.DAY_OF_MONTH, day);
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.HOUR_OF_DAY, 10);
+ cal.set(Calendar.MINUTE, 2);
+ cal.set(Calendar.SECOND, 5);
+ cal.set(Calendar.MILLISECOND, 101);
+ Date d = new Date(cal.getTimeInMillis());
+ return d;
+ }
+
+ private static String[] upsert(String...args) {
+ return args;
+ }
+
+ private static String[] select(String...args) {
+ return args;
+ }
+
+ private static BigDecimal bdec(double d) {
+ return BigDecimal.valueOf(d);
+ }
+
+ private static BigInteger bint(long l) {
+ return BigInteger.valueOf(l);
+ }
+
+ private static class WhereCondition {
+ final String lhs;
+ final String operator;
+ final String rhs;
+
+ WhereCondition(String lhs, String operator, String rhs) {
+ this.lhs = lhs;
+ this.operator = operator;
+ this.rhs = rhs;
+ }
+
+ static WhereCondition reverse(WhereCondition whereCondition) {
+
+ if (whereCondition == null) {
+ return null;
+ }
+
+ if (whereCondition.operator.equalsIgnoreCase("IN") || whereCondition.operator.equalsIgnoreCase("LIKE")) {
+ return whereCondition;
+ } else {
+ return new WhereCondition(whereCondition.rhs, whereCondition.getReversedOperator(), whereCondition.lhs);
+ }
+ }
+
+ static String appendWhere(WhereCondition whereCondition, String query) {
+ if (whereCondition == null) {
+ return query;
+ }
+ return query + " WHERE " + whereCondition.lhs + " " + whereCondition.operator + " " + whereCondition.rhs;
+ }
+
+ private String getReversedOperator() {
+ if (operator.equals("<")) {
+ return ">";
+ } else if (operator.equals(">")) {
+ return "<";
+ }
+ return operator;
+ }
+ }
+
+ private static class HavingCondition {
+
+ private String groupby;
+ private String having;
+
+ HavingCondition(String groupby, String having) {
+ this.groupby = groupby;
+ this.having = having;
+ }
+
+ static String appendHaving(HavingCondition havingCondition, String query) {
+ if (havingCondition == null) {
+ return query;
+ }
+ return query + " GROUP BY " + havingCondition.groupby + " HAVING " + havingCondition.having + " ";
+ }
+ }
+
+ private static class OrderBy {
+
+ enum Direction {
+
+ ASC, DESC;
+
+ Direction reverse() {
+ if (this == ASC) {
+ return DESC;
+ }
+ return ASC;
+ }
+ }
+
+ private List<String> columnNames = Lists.newArrayList();
+ private List<Direction> directions = Lists.newArrayList();
+
+ OrderBy() {
+ }
+
+ OrderBy(String columnName, Direction orderBy) {
+ add(columnName, orderBy);
+ }
+
+ void add(String columnName, Direction direction) {
+ columnNames.add(columnName);
+ directions.add(direction);
+ }
+
+ static OrderBy reverse(OrderBy orderBy) {
+
+ if (orderBy == null) {
+ return null;
+ }
+
+ List<Direction> reversedDirections = Lists.newArrayList();
+ for (Direction dir : orderBy.directions) {
+ reversedDirections.add(dir.reverse());
+ }
+ OrderBy reversedOrderBy = new OrderBy();
+ reversedOrderBy.columnNames = orderBy.columnNames;
+ reversedOrderBy.directions = reversedDirections;
+ return reversedOrderBy;
+ }
+
+ static String appendOrderBy(OrderBy orderBy, String query) {
+ if (orderBy == null || orderBy.columnNames.isEmpty()) {
+ return query;
+ }
+ query += " ORDER BY ";
+ for (int i = 0; i < orderBy.columnNames.size(); i++) {
+ query += orderBy.columnNames.get(i) + " " + orderBy.directions.get(i).toString() + " ";
+ }
+
+ query += " LIMIT 1000 ";
+
+ return query;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
index 30a2bb7..9845498 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
@@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.client.HTableInterface;
import org.apache.phoenix.coprocessor.MetaDataProtocol;
@@ -650,7 +651,7 @@ public class FromCompiler {
PTableType.SUBQUERY, null, MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM,
null, null, columns, null, null, Collections.<PTable>emptyList(),
false, Collections.<PName>emptyList(), null, null, false, false, false, null,
- null, null);
+ null, null, false);
String alias = subselectNode.getAlias();
TableRef tableRef = new TableRef(alias, t, MetaDataProtocol.MIN_TABLE_TIMESTAMP, false);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
index 78f54e8..e4ca5d9 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
@@ -1297,8 +1297,12 @@ public class JoinCompiler {
}
return PTableImpl.makePTable(left.getTenantId(), left.getSchemaName(),
- PNameFactory.newName(SchemaUtil.getTableName(left.getName().getString(), right.getName().getString())), left.getType(), left.getIndexState(), left.getTimeStamp(), left.getSequenceNumber(), left.getPKName(), left.getBucketNum(), merged,
- left.getParentSchemaName(), left.getParentTableName(), left.getIndexes(), left.isImmutableRows(), Collections.<PName>emptyList(), null, null, PTable.DEFAULT_DISABLE_WAL, left.isMultiTenant(), left.getStoreNulls(), left.getViewType(), left.getViewIndexId(), left.getIndexType());
+ PNameFactory.newName(SchemaUtil.getTableName(left.getName().getString(), right.getName().getString())),
+ left.getType(), left.getIndexState(), left.getTimeStamp(), left.getSequenceNumber(), left.getPKName(),
+ left.getBucketNum(), merged,left.getParentSchemaName(), left.getParentTableName(), left.getIndexes(),
+ left.isImmutableRows(), Collections.<PName>emptyList(), null, null, PTable.DEFAULT_DISABLE_WAL,
+ left.isMultiTenant(), left.getStoreNulls(), left.getViewType(), left.getViewIndexId(), left.getIndexType(),
+ left.rowKeyOrderOptimizable());
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
index f0406d4..7275b64 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
@@ -122,8 +122,8 @@ public class OrderByCompiler {
boolean isAscending = node.isAscending();
boolean isNullsLast = node.isNullsLast();
tracker.track(expression, isAscending ? SortOrder.ASC : SortOrder.DESC, isNullsLast);
- // FIXME: this isn't correct. If we have a schema where column A is DESC,
- // An ORDER BY A should still be ASC.
+ // If we have a schema where column A is DESC, reverse the sort order and nulls last
+ // since this is the order they actually are in.
if (expression.getSortOrder() == SortOrder.DESC) {
isAscending = !isAscending;
isNullsLast = !isNullsLast;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java
index 1c31606..70ae231 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java
@@ -79,8 +79,9 @@ public class OrderPreservingTracker {
public OrderPreservingTracker(StatementContext context, GroupBy groupBy, Ordering ordering, int nNodes, TupleProjector projector) {
int pkPositionOffset = 0;
+ PTable table = context.getResolver().getTables().get(0).getTable();
+ isOrderPreserving = table.rowKeyOrderOptimizable();
if (groupBy.isEmpty()) { // FIXME: would the below table have any of these set in the case of a GROUP BY?
- PTable table = context.getResolver().getTables().get(0).getTable();
boolean isSalted = table.getBucketNum() != null;
boolean isMultiTenant = context.getConnection().getTenantId() != null && table.isMultiTenant();
boolean isSharedViewIndex = table.getViewIndexId() != null;
@@ -117,10 +118,12 @@ public class OrderPreservingTracker {
*/
if (!groupBy.isEmpty() && !groupBy.isOrderPreserving()) {
isOrderPreserving = false;
+ isReverse = false;
return;
}
} else if (!isReverse){
isOrderPreserving = false;
+ isReverse = false;
return;
}
} else {
@@ -128,12 +131,14 @@ public class OrderPreservingTracker {
isReverse = false;
} else if (isReverse){
isOrderPreserving = false;
+ isReverse = false;
return;
}
}
if (node.isNullable()) {
if (!Boolean.valueOf(isNullsLast).equals(isReverse)) {
isOrderPreserving = false;
+ isReverse = false;
return;
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
index 473e579..80cfbfe 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ScanRanges.java
@@ -32,6 +32,7 @@ import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.filter.SkipScanFilter;
import org.apache.phoenix.query.KeyRange;
import org.apache.phoenix.query.KeyRange.Bound;
+import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.RowKeySchema;
import org.apache.phoenix.schema.SaltingUtil;
import org.apache.phoenix.util.ByteUtil;
@@ -82,7 +83,9 @@ public class ScanRanges {
}
}
ranges = Collections.singletonList(keyRanges);
- if (keys.size() > 1) {
+ // Treat as binary if descending because we've got a separator byte at the end
+ // which is not part of the value.
+ if (keys.size() > 1 || SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), false, schema.getField(0)) == QueryConstants.DESC_SEPARATOR_BYTE) {
schema = SchemaUtil.VAR_BINARY_SCHEMA;
slotSpan = ScanUtil.SINGLE_COLUMN_SLOT_SPAN;
} else {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
index ee65280..c6aa546 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
@@ -152,7 +152,7 @@ public class TupleProjectionCompiler {
table.getBucketNum(), projectedColumns, table.getParentSchemaName(),
table.getParentName(), table.getIndexes(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null,
table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(),
- table.getIndexType());
+ table.getIndexType(), table.rowKeyOrderOptimizable());
}
public static PTable createProjectedTable(TableRef tableRef, List<ColumnRef> sourceColumnRefs, boolean retainPKColumns) throws SQLException {
@@ -179,7 +179,7 @@ public class TupleProjectionCompiler {
retainPKColumns ? table.getBucketNum() : null, projectedColumns, null,
null, Collections.<PTable>emptyList(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null,
table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(),
- null);
+ null, table.rowKeyOrderOptimizable());
}
// For extracting column references from single select statement
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
index 269232e..942e244 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
@@ -80,8 +80,9 @@ public class UnionCompiler {
}
Long scn = statement.getConnection().getSCN();
PTable tempTable = PTableImpl.makePTable(statement.getConnection().getTenantId(), UNION_SCHEMA_NAME, UNION_TABLE_NAME,
- PTableType.SUBQUERY, null, HConstants.LATEST_TIMESTAMP, scn == null ? HConstants.LATEST_TIMESTAMP : scn, null, null, projectedColumns, null, null, null,
- true, null, null, null, true, true, true, null, null, null);
+ PTableType.SUBQUERY, null, HConstants.LATEST_TIMESTAMP, scn == null ? HConstants.LATEST_TIMESTAMP : scn, null, null,
+ projectedColumns, null, null, null,
+ true, null, null, null, true, true, true, null, null, null, false);
TableRef tableRef = new TableRef(null, tempTable, 0, false);
return tableRef;
}
[27/50] [abbrv] phoenix git commit: PHOENIX-978: Allow views to
extend parent's PK only if parent's last PK column is fixed length
Posted by ma...@apache.org.
PHOENIX-978: Allow views to extend parent's PK only if parent's last PK column is fixed length
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/66705d51
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/66705d51
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/66705d51
Branch: refs/heads/calcite
Commit: 66705d5170496bed7c39bd484517722ac8d09a13
Parents: a772a4a
Author: Eli Levine <el...@apache.org>
Authored: Wed Jul 8 18:46:43 2015 -0700
Committer: Thomas D'Silva <td...@salesforce.com>
Committed: Mon Jul 13 17:36:58 2015 -0700
----------------------------------------------------------------------
.../apache/phoenix/end2end/AlterTableIT.java | 9 ++----
.../java/org/apache/phoenix/end2end/ViewIT.java | 17 ++++++++++
.../phoenix/exception/SQLExceptionCode.java | 1 +
.../apache/phoenix/schema/MetaDataClient.java | 33 ++++++++++++++++++++
4 files changed, 54 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/66705d51/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 fbaded0..0425933 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
@@ -64,7 +64,6 @@ import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.ReadOnlyProps;
import org.apache.phoenix.util.SchemaUtil;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
import com.google.common.base.Objects;
@@ -2132,15 +2131,13 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
@Test
- @Ignore
- // enable this test after https://issues.apache.org/jira/browse/PHOENIX-978 is fixed
public void testAddExistingViewPkColumnToBaseTableWithViews() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
try {
conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW ("
+ " ID char(10) NOT NULL,"
+ " COL1 integer NOT NULL,"
- + " COL2 bigint NOT NULL,"
+ + " COL2 integer NOT NULL,"
+ " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)"
+ " )");
assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, -1, "ID", "COL1", "COL2");
@@ -2169,7 +2166,7 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
}
// add the pk column of the view to the base table
- conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL PRIMARY KEY");
+ conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW ADD VIEW_COL1 DECIMAL(10,2) PRIMARY KEY");
assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 1, 4, -1, "ID", "COL1", "COL2", "VIEW_COL1");
assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 1, 5, 4, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2");
@@ -2179,7 +2176,7 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT {
assertEquals(rs.getString(1), "view1");
assertEquals(rs.getInt(2), 12);
assertEquals(rs.getInt(3), 13);
- assertEquals(rs.getInt(4), 14);
+ assertEquals(rs.getBigDecimal(4).intValue(), 14);
assertFalse(rs.next());
// query view
http://git-wip-us.apache.org/repos/asf/phoenix/blob/66705d51/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
index db38ab3..1d8af35 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
@@ -18,6 +18,7 @@
package org.apache.phoenix.end2end;
import static com.google.common.collect.Lists.newArrayListWithExpectedSize;
+import static org.apache.phoenix.exception.SQLExceptionCode.CANNOT_MODIFY_VIEW_PK;
import static org.apache.phoenix.exception.SQLExceptionCode.NOT_NULLABLE_COLUMN_IN_ROW_KEY;
import static org.apache.phoenix.util.TestUtil.analyzeTable;
import static org.apache.phoenix.util.TestUtil.getAllSplits;
@@ -522,6 +523,22 @@ public class ViewIT extends BaseViewIT {
assertPKs(rs, new String[] {"K1", "K2", "K3", "K4"});
}
+ @Test
+ public void testViewAddsPKColumnWhoseParentsLastPKIsVarLength() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ String ddl = "CREATE TABLE tp (k1 INTEGER NOT NULL, k2 VARCHAR NOT NULL, v1 DECIMAL, CONSTRAINT pk PRIMARY KEY (k1, k2))";
+ conn.createStatement().execute(ddl);
+ ddl = "CREATE VIEW v1 AS SELECT * FROM tp WHERE v1 = 1.0";
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER VIEW V1 ADD k3 VARCHAR PRIMARY KEY, k4 VARCHAR PRIMARY KEY, v2 INTEGER";
+ try {
+ conn.createStatement().execute(ddl);
+ fail("View cannot extend PK if parent's last PK is variable length. See https://issues.apache.org/jira/browse/PHOENIX-978.");
+ } catch (SQLException e) {
+ assertEquals(CANNOT_MODIFY_VIEW_PK.getErrorCode(), e.getErrorCode());
+ }
+ }
+
@Test(expected=ColumnAlreadyExistsException.class)
public void testViewAddsClashingPKColumn() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
http://git-wip-us.apache.org/repos/asf/phoenix/blob/66705d51/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 b9f81fb..195450c 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
@@ -189,6 +189,7 @@ public enum SQLExceptionCode {
NOT_NULLABLE_COLUMN_IN_ROW_KEY(1006, "42J04", "Only nullable columns may be added to a multi-part row key."),
VARBINARY_LAST_PK(1015, "42J04", "Cannot add column to table when the last PK column is of type VARBINARY or ARRAY."),
NULLABLE_FIXED_WIDTH_LAST_PK(1023, "42J04", "Cannot add column to table when the last PK column is nullable and fixed width."),
+ CANNOT_MODIFY_VIEW_PK(1036, "42J04", "Cannot modify the primary key of a VIEW if last PK column of parent is variable length."),
BASE_TABLE_COLUMN(1037, "42J04", "Cannot modify columns of base table used by tenant-specific tables."),
// Key/value column related errors
KEY_VALUE_NOT_NULL(1007, "42K01", "A key/value column may not be declared as not null."),
http://git-wip-us.apache.org/repos/asf/phoenix/blob/66705d51/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 9d0c1aa..56c1aa2 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
@@ -79,6 +79,8 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_TYPE;
import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT;
import static org.apache.phoenix.query.QueryServices.DROP_METADATA_ATTRIB;
import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_DROP_METADATA;
+import static org.apache.phoenix.schema.PTable.ViewType.MAPPED;
+import static org.apache.phoenix.schema.PTableType.VIEW;
import java.io.IOException;
import java.sql.Connection;
@@ -162,6 +164,8 @@ import org.apache.phoenix.parse.PFunction.FunctionArgument;
import org.apache.phoenix.parse.ParseNode;
import org.apache.phoenix.parse.ParseNodeFactory;
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.parse.UpdateStatisticsStatement;
import org.apache.phoenix.query.ConnectionQueryServices.Feature;
@@ -1677,6 +1681,9 @@ public class MetaDataClient {
.setColumnName(column.getName().getString())
.build().buildException();
}
+ if (tableType == PTableType.VIEW && viewType != ViewType.MAPPED) {
+ throwIfLastPKOfParentIsFixedLength(parent, schemaName, tableName, colDef);
+ }
if (!pkColumns.add(column)) {
throw new ColumnAlreadyExistsException(schemaName, tableName, column.getName().getString());
}
@@ -2421,6 +2428,9 @@ public class MetaDataClient {
.setColumnName(colDef.getColumnDefName().getColumnName()).build().buildException();
}
}
+ if (colDef != null && colDef.isPK() && table.getType() == VIEW && table.getViewType() != MAPPED) {
+ throwIfLastPKOfParentIsFixedLength(getParentOfView(table), schemaName, tableName, colDef);
+ }
PColumn column = newColumn(position++, colDef, PrimaryKeyConstraint.EMPTY, table.getDefaultFamilyName() == null ? null : table.getDefaultFamilyName().getString(), true);
columns.add(column);
String pkName = null;
@@ -2956,4 +2966,27 @@ public class MetaDataClient {
return table.getTableStats();
}
+ private void throwIfLastPKOfParentIsFixedLength(PTable parent, String viewSchemaName, String viewName, ColumnDef col) throws SQLException {
+ if (isLastPKVariableLength(parent)) {
+ throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_MODIFY_VIEW_PK)
+ .setSchemaName(viewSchemaName)
+ .setTableName(viewName)
+ .setColumnName(col.getColumnDefName().getColumnName())
+ .build().buildException(); }
+ }
+
+ private boolean isLastPKVariableLength(PTable table) {
+ List<PColumn> pkColumns = table.getPKColumns();
+ if (pkColumns.size() < 1) {
+ return false;
+ } else {
+ return !pkColumns.get(pkColumns.size()-1).getDataType().isFixedWidth();
+ }
+ }
+
+ private PTable getParentOfView(PTable view) throws SQLException {
+ SelectStatement select = new SQLParser(view.getViewStatement()).parseQuery();
+ String parentName = SchemaUtil.normalizeFullTableName(select.getFrom().toString().trim());
+ return connection.getMetaDataCache().getTable(new PTableKey(view.getTenantId(), parentName));
+ }
}
[24/50] [abbrv] phoenix git commit: PHOENIX-2113 Include
log4j.properties in Pherf so runtime logging is displayed on console by
default
Posted by ma...@apache.org.
PHOENIX-2113 Include log4j.properties in Pherf so runtime logging is displayed on console by default
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/052836c7
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/052836c7
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/052836c7
Branch: refs/heads/calcite
Commit: 052836c72c97de6580dda22fb485b7e3fa6d277d
Parents: 300de02
Author: Mujtaba <mu...@apache.org>
Authored: Mon Jul 13 11:50:47 2015 -0700
Committer: Mujtaba <mu...@apache.org>
Committed: Mon Jul 13 11:50:47 2015 -0700
----------------------------------------------------------------------
phoenix-pherf/config/log4j.properties | 58 ++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/052836c7/phoenix-pherf/config/log4j.properties
----------------------------------------------------------------------
diff --git a/phoenix-pherf/config/log4j.properties b/phoenix-pherf/config/log4j.properties
new file mode 100644
index 0000000..a6673c4
--- /dev/null
+++ b/phoenix-pherf/config/log4j.properties
@@ -0,0 +1,58 @@
+#
+#
+# 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.
+#
+#
+
+log4j.rootLogger=INFO,console
+log4j.threshold=INFO
+log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.DRFA.File=pherf.log
+
+# Rollver at midnight
+log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
+
+# 30-day backup
+#log4j.appender.DRFA.MaxBackupIndex=30
+log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
+
+# Pattern format: Date LogLevel LoggerName LogMessage
+log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
+
+# Debugging Pattern format
+#log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
+
+#
+# Null Appender
+#
+log4j.appender.NullAppender=org.apache.log4j.varia.NullAppender
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n
+
+# Custom Logging levels
+log4j.logger.org.apache.zookeeper=ERROR
+log4j.logger.org.apache.hadoop.hbase.zookeeper.RecoverableZooKeeper=ERROR
+log4j.logger.org.apache.hadoop.hbase.zookeeper.ZKUtil=ERROR
+log4j.logger.org.apache.hadoop.hbase.HBaseConfiguration=ERROR
[34/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/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 7b39a28..e12f5a4 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
@@ -150,8 +150,10 @@ public class UpsertCompiler {
SQLExceptionCode.DATA_EXCEEDS_MAX_CAPACITY).setColumnName(column.getName().getString())
.setMessage("value=" + column.getDataType().toStringLiteral(ptr, null)).build()
.buildException(); }
- column.getDataType().coerceBytes(ptr, value, column.getDataType(), precision, scale,
- SortOrder.getDefault(), column.getMaxLength(), column.getScale(), column.getSortOrder());
+ column.getDataType().coerceBytes(ptr, value, column.getDataType(),
+ precision, scale, SortOrder.getDefault(),
+ column.getMaxLength(), column.getScale(), column.getSortOrder(),
+ table.rowKeyOrderOptimizable());
values[i] = ByteUtil.copyKeyBytesIfNecessary(ptr);
}
setValues(values, pkSlotIndexes, columnIndexes, table, mutation, statement);
@@ -772,6 +774,7 @@ public class UpsertCompiler {
final SequenceManager sequenceManager = context.getSequenceManager();
// Next evaluate all the expressions
int nodeIndex = nodeIndexOffset;
+ PTable table = tableRef.getTable();
Tuple tuple = sequenceManager.getSequenceCount() == 0 ? null :
sequenceManager.newSequenceTuple(null);
for (Expression constantExpression : constantExpressions) {
@@ -793,9 +796,10 @@ public class UpsertCompiler {
.setMessage("value=" + constantExpression.toString()).build().buildException();
}
}
- column.getDataType().coerceBytes(ptr, value,
- constantExpression.getDataType(), constantExpression.getMaxLength(), constantExpression.getScale(), constantExpression.getSortOrder(),
- column.getMaxLength(), column.getScale(),column.getSortOrder());
+ column.getDataType().coerceBytes(ptr, value, constantExpression.getDataType(),
+ constantExpression.getMaxLength(), constantExpression.getScale(), constantExpression.getSortOrder(),
+ column.getMaxLength(), column.getScale(),column.getSortOrder(),
+ table.rowKeyOrderOptimizable());
if (overlapViewColumns.contains(column) && Bytes.compareTo(ptr.get(), ptr.getOffset(), ptr.getLength(), column.getViewConstant(), 0, column.getViewConstant().length-1) != 0) {
throw new SQLExceptionInfo.Builder(
SQLExceptionCode.CANNOT_UPDATE_VIEW_COLUMN)
@@ -814,7 +818,7 @@ public class UpsertCompiler {
}
}
Map<ImmutableBytesPtr, RowMutationState> mutation = Maps.newHashMapWithExpectedSize(1);
- setValues(values, pkSlotIndexes, columnIndexes, tableRef.getTable(), mutation, statement);
+ setValues(values, pkSlotIndexes, columnIndexes, table, mutation, statement);
return new MutationState(tableRef, mutation, 0, maxSize, connection);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
index 0cbef11..332f293 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
@@ -61,7 +61,9 @@ import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.RowKeySchema;
import org.apache.phoenix.schema.SaltingUtil;
import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.ValueSchema.Field;
import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PArrayDataType;
import org.apache.phoenix.schema.types.PChar;
import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.schema.types.PVarbinary;
@@ -194,8 +196,9 @@ public class WhereOptimizer {
if (hasMinMaxRange) {
System.arraycopy(tenantIdBytes, 0, minMaxRangePrefix, minMaxRangeOffset, tenantIdBytes.length);
minMaxRangeOffset += tenantIdBytes.length;
- if (!schema.getField(pkPos).getDataType().isFixedWidth()) {
- minMaxRangePrefix[minMaxRangeOffset] = QueryConstants.SEPARATOR_BYTE;
+ Field f = schema.getField(pkPos);
+ if (!f.getDataType().isFixedWidth()) {
+ minMaxRangePrefix[minMaxRangeOffset] = SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), tenantIdBytes.length==0, f);
minMaxRangeOffset++;
}
}
@@ -259,6 +262,8 @@ public class WhereOptimizer {
hasNonPointKey = true;
}
}
+ keyRanges = transformKeyRangesIfNecessary(slot, context);
+
hasMultiRanges |= keyRanges.size() > 1;
// Force a range scan if we've encountered a multi-span slot (i.e. RVC)
// and a non point key, as our skip scan only handles fully qualified
@@ -317,6 +322,45 @@ public class WhereOptimizer {
}
}
+ // Special hack for PHOENIX-2067 to change the constant array to match
+ // the separators used for descending, variable length arrays.
+ // Note that there'd already be a coerce expression around the constant
+ // to convert it to the right type, so we shouldn't do that here.
+ private static List<KeyRange> transformKeyRangesIfNecessary(KeyExpressionVisitor.KeySlot slot, StatementContext context) {
+ KeyPart keyPart = slot.getKeyPart();
+ List<KeyRange> keyRanges = slot.getKeyRanges();
+ PColumn column = keyPart.getColumn();
+ if (column != null) {
+ PDataType type = column.getDataType();
+ PTable table = context.getCurrentTable().getTable();
+ // Constants are always build with rowKeyOptimizable as true, using the correct separators
+ // We only need to do this conversion if we have a table that has not yet been converted.
+ if (type != null && type.isArrayType() && column.getSortOrder() == SortOrder.DESC && !PArrayDataType.arrayBaseType(type).isFixedWidth() && !table.rowKeyOrderOptimizable()) {
+ ImmutableBytesWritable ptr = context.getTempPtr();
+ List<KeyRange> newKeyRanges = Lists.newArrayListWithExpectedSize(keyRanges.size());
+ for (KeyRange keyRange : keyRanges) {
+ byte[] lower = keyRange.getLowerRange();
+ if (!keyRange.lowerUnbound()) {
+ ptr.set(lower);;
+ type.coerceBytes(ptr, null, type, null, null, SortOrder.DESC, null, null, SortOrder.DESC, false);
+ lower = ByteUtil.copyKeyBytesIfNecessary(ptr);
+ }
+ byte[] upper = keyRange.getUpperRange();
+ if (!keyRange.upperUnbound()) {
+ ptr.set(upper);;
+ type.coerceBytes(ptr, null, type, null, null, SortOrder.DESC, null, null, SortOrder.DESC, false);
+ upper = ByteUtil.copyKeyBytesIfNecessary(ptr);
+ }
+ keyRange = KeyRange.getKeyRange(lower, keyRange.isLowerInclusive(), upper, keyRange.isUpperInclusive());
+ newKeyRanges.add(keyRange);
+ }
+
+ return newKeyRanges;
+ }
+ }
+ return keyRanges;
+ }
+
/**
* Get an optimal combination of key expressions for hash join key range optimization.
* @return returns true if the entire combined expression is covered by key range optimization
@@ -996,6 +1040,9 @@ public class WhereOptimizer {
// Handles cases like WHERE substr(foo,1,3) IN ('aaa','bbb')
for (Expression key : keyExpressions) {
KeyRange range = childPart.getKeyRange(CompareOp.EQUAL, key);
+ if (range == null) {
+ return null;
+ }
if (range != KeyRange.EMPTY_RANGE) { // null means it can't possibly be in range
ranges.add(range);
}
@@ -1393,7 +1440,7 @@ public class WhereOptimizer {
return null; // Shouldn't happen
}
ImmutableBytesWritable ptr = context.getTempPtr();
- if (!rhs.evaluate(null, ptr) || ptr.getLength()==0) {
+ if (!rhs.evaluate(null, ptr)) { // Don't return if evaluated to null
return null;
}
byte[] key = ByteUtil.copyKeyBytesIfNecessary(ptr);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java
index d9e64e2..c8d4926 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java
@@ -88,6 +88,8 @@ abstract public class BaseScannerRegionObserver extends BaseRegionObserver {
public static final String ANALYZE_TABLE = "_ANALYZETABLE";
public static final String GUIDEPOST_WIDTH_BYTES = "_GUIDEPOST_WIDTH_BYTES";
public static final String GUIDEPOST_PER_REGION = "_GUIDEPOST_PER_REGION";
+ public static final String UPGRADE_DESC_ROW_KEY = "_UPGRADE_DESC_ROW_KEY";
+
/**
* Attribute name used to pass custom annotations in Scans and Mutations (later). Custom annotations
* are used to augment log lines emitted by Phoenix. See https://issues.apache.org/jira/browse/PHOENIX-1198.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
index 1be0548..dcfe61d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java
@@ -183,6 +183,7 @@ import org.apache.phoenix.util.QueryUtil;
import org.apache.phoenix.util.ScanUtil;
import org.apache.phoenix.util.SchemaUtil;
import org.apache.phoenix.util.ServerUtil;
+import org.apache.phoenix.util.UpgradeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -213,6 +214,10 @@ import com.google.protobuf.Service;
public class MetaDataEndpointImpl extends MetaDataProtocol implements CoprocessorService, Coprocessor {
private static final Logger logger = LoggerFactory.getLogger(MetaDataEndpointImpl.class);
+ // Column to track tables that have been upgraded based on PHOENIX-2067
+ public static final String ROW_KEY_ORDER_OPTIMIZABLE = "ROW_KEY_ORDER_OPTIMIZABLE";
+ public static final byte[] ROW_KEY_ORDER_OPTIMIZABLE_BYTES = Bytes.toBytes(ROW_KEY_ORDER_OPTIMIZABLE);
+
// KeyValues for Table
private static final KeyValue TABLE_TYPE_KV = createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, TABLE_TYPE_BYTES);
private static final KeyValue TABLE_SEQ_NUM_KV = createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, TABLE_SEQ_NUM_BYTES);
@@ -233,6 +238,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
private static final KeyValue STORE_NULLS_KV = createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, STORE_NULLS_BYTES);
private static final KeyValue EMPTY_KEYVALUE_KV = createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, QueryConstants.EMPTY_COLUMN_BYTES);
private static final KeyValue BASE_COLUMN_COUNT_KV = createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, PhoenixDatabaseMetaData.BASE_COLUMN_COUNT_BYTES);
+ private static final KeyValue ROW_KEY_ORDER_OPTIMIZABLE_KV = createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, ROW_KEY_ORDER_OPTIMIZABLE_BYTES);
private static final List<KeyValue> TABLE_KV_COLUMNS = Arrays.<KeyValue>asList(
EMPTY_KEYVALUE_KV,
@@ -253,7 +259,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
INDEX_TYPE_KV,
INDEX_DISABLE_TIMESTAMP_KV,
STORE_NULLS_KV,
- BASE_COLUMN_COUNT_KV
+ BASE_COLUMN_COUNT_KV,
+ ROW_KEY_ORDER_OPTIMIZABLE_KV
);
static {
Collections.sort(TABLE_KV_COLUMNS, KeyValue.COMPARATOR);
@@ -276,6 +283,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
private static final int INDEX_TYPE_INDEX = TABLE_KV_COLUMNS.indexOf(INDEX_TYPE_KV);
private static final int STORE_NULLS_INDEX = TABLE_KV_COLUMNS.indexOf(STORE_NULLS_KV);
private static final int BASE_COLUMN_COUNT_INDEX = TABLE_KV_COLUMNS.indexOf(BASE_COLUMN_COUNT_KV);
+ private static final int ROW_KEY_ORDER_OPTIMIZABLE_INDEX = TABLE_KV_COLUMNS.indexOf(ROW_KEY_ORDER_OPTIMIZABLE_KV);
// KeyValues for Column
private static final KeyValue DECIMAL_DIGITS_KV = createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, DECIMAL_DIGITS_BYTES);
@@ -782,6 +790,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
Cell baseColumnCountKv = tableKeyValues[BASE_COLUMN_COUNT_INDEX];
int baseColumnCount = baseColumnCountKv == null ? 0 : PInteger.INSTANCE.getCodec().decodeInt(baseColumnCountKv.getValueArray(),
baseColumnCountKv.getValueOffset(), SortOrder.getDefault());
+ Cell rowKeyOrderOptimizableKv = tableKeyValues[ROW_KEY_ORDER_OPTIMIZABLE_INDEX];
+ boolean rowKeyOrderOptimizable = rowKeyOrderOptimizableKv == null ? false : Boolean.TRUE.equals(PBoolean.INSTANCE.toObject(rowKeyOrderOptimizableKv.getValueArray(), rowKeyOrderOptimizableKv.getValueOffset(), rowKeyOrderOptimizableKv.getValueLength()));
List<PColumn> columns = Lists.newArrayListWithExpectedSize(columnCount);
List<PTable> indexes = new ArrayList<PTable>();
@@ -826,7 +836,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
return PTableImpl.makePTable(tenantId, schemaName, tableName, tableType, indexState, timeStamp,
tableSeqNum, pkName, saltBucketNum, columns, tableType == INDEX ? schemaName : null,
tableType == INDEX ? dataTableName : null, indexes, isImmutableRows, physicalTables, defaultFamilyName, viewStatement,
- disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, stats, baseColumnCount);
+ disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, stats, baseColumnCount, rowKeyOrderOptimizable);
}
private PFunction getFunction(RegionScanner scanner, final boolean isReplace, long clientTimeStamp, List<Mutation> deleteMutationsForReplace)
@@ -1058,7 +1068,6 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
return null;
}
-
@Override
public void createTable(RpcController controller, CreateTableRequest request,
RpcCallback<MetaDataResponse> done) {
@@ -1145,6 +1154,14 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
return;
}
}
+ PTableType tableType = MetaDataUtil.getTableType(tableMetadata, GenericKeyValueBuilder.INSTANCE,
+ new ImmutableBytesWritable());
+ // Add cell for ROW_KEY_ORDER_OPTIMIZABLE = true, as we know that new tables
+ // conform the correct row key. The exception is for a VIEW, which the client
+ // sends over depending on its base physical table.
+ if (tableType != PTableType.VIEW) {
+ UpgradeUtil.addRowKeyOrderOptimizableCell(tableMetadata, key, clientTimeStamp);
+ }
// TODO: Switch this to Region#batchMutate when we want to support indexes on the
// system
// table. Basically, we get all the locks that we don't already hold for all the
@@ -1563,7 +1580,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
} else {
// server-side, except for indexing, we always expect the keyvalues to be standard KeyValues
PTableType expectedType = MetaDataUtil.getTableType(tableMetadata, GenericKeyValueBuilder.INSTANCE,
- new ImmutableBytesPtr());
+ new ImmutableBytesWritable());
// We said to drop a table, but found a view or visa versa
if (type != expectedType) { return new MetaDataMutationResult(MutationCode.TABLE_NOT_FOUND,
EnvironmentEdgeManager.currentTimeMillis(), null); }
@@ -1612,6 +1629,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
if (view.getBaseColumnCount() == QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT) {
// if a view has divorced itself from the base table, we don't allow schema changes
// to be propagated to it.
+ // FIXME: we should allow the update, but just not propagate it to this view
+ // The one exception is PK changes which need to be propagated to diverged views as well
return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null);
}
int numColsAddedToBaseTable = 0;
@@ -1846,6 +1865,9 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
// add index row header key to the invalidate list to force clients to fetch the latest meta-data
invalidateList.add(new ImmutableBytesPtr(indexHeaderRowKey));
+ if (index.rowKeyOrderOptimizable()) {
+ UpgradeUtil.addRowKeyOrderOptimizableCell(mutationsForAddingColumnsToViews, indexHeaderRowKey, clientTimeStamp);
+ }
mutationsForAddingColumnsToViews.add(indexHeaderRowMutation);
}
}
@@ -1866,6 +1888,9 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
viewHeaderRowPut.addColumn(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES,
PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES, clientTimeStamp, viewSequencePtr);
mutationsForAddingColumnsToViews.add(viewHeaderRowPut);
+ if (view.rowKeyOrderOptimizable()) {
+ UpgradeUtil.addRowKeyOrderOptimizableCell(mutationsForAddingColumnsToViews, viewKey, clientTimeStamp);
+ }
// Update positions of view columns
for (PColumn column : view.getColumns()) {
@@ -1912,7 +1937,10 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
byte[] schemaName = rowKeyMetaData[SCHEMA_NAME_INDEX];
byte[] tableName = rowKeyMetaData[TABLE_NAME_INDEX];
PTableType type = table.getType();
- List<Mutation> mutationsForAddingColumnsToViews = Collections.emptyList();
+ byte[] tableHeaderRowKey = SchemaUtil.getTableKey(tenantId,
+ schemaName, tableName);
+ // Size for worst case - all new columns are PK column
+ List<Mutation> mutationsForAddingColumnsToViews = Lists.newArrayListWithExpectedSize(tableMetaData.size() * ( 1 + table.getIndexes().size()));
/*
* If adding a column to a view, we don't want to propagate those meta-data changes to the child
* view hierarchy. This is because our check of finding child views is expensive and we want making
@@ -1973,6 +2001,17 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
continue;
} catch (ColumnNotFoundException e) {
if (addingPKColumn) {
+ // We may be adding a DESC column, so if table is already
+ // able to be rowKeyOptimized, it should continue to be so.
+ if (table.rowKeyOrderOptimizable()) {
+ UpgradeUtil.addRowKeyOrderOptimizableCell(mutationsForAddingColumnsToViews, tableHeaderRowKey, clientTimeStamp);
+ } else if (table.getType() == PTableType.VIEW){
+ // Don't allow view PK to diverge from table PK as our upgrade code
+ // does not handle this.
+ return new MetaDataMutationResult(
+ MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager
+ .currentTimeMillis(), null);
+ }
// Add all indexes to invalidate list, as they will all be
// adding the same PK column. No need to lock them, as we
// have the parent table lock at this point.
@@ -1981,6 +2020,13 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
.getTableKey(tenantId, index.getSchemaName()
.getBytes(), index.getTableName()
.getBytes())));
+ // We may be adding a DESC column, so if index is already
+ // able to be rowKeyOptimized, it should continue to be so.
+ if (index.rowKeyOrderOptimizable()) {
+ byte[] indexHeaderRowKey = SchemaUtil.getTableKey(index.getTenantId() == null ? ByteUtil.EMPTY_BYTE_ARRAY : index.getTenantId().getBytes(),
+ index.getSchemaName().getBytes(), index.getTableName().getBytes());
+ UpgradeUtil.addRowKeyOrderOptimizableCell(mutationsForAddingColumnsToViews, indexHeaderRowKey, clientTimeStamp);
+ }
}
}
continue;
@@ -2315,7 +2361,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
byte[] tenantId = rowKeyMetaData[PhoenixDatabaseMetaData.TENANT_ID_INDEX];
schemaName = rowKeyMetaData[PhoenixDatabaseMetaData.SCHEMA_NAME_INDEX];
tableName = rowKeyMetaData[PhoenixDatabaseMetaData.TABLE_NAME_INDEX];
- byte[] key = SchemaUtil.getTableKey(tenantId, schemaName, tableName);
+ final byte[] key = SchemaUtil.getTableKey(tenantId, schemaName, tableName);
Region region = env.getRegion();
MetaDataMutationResult result = checkTableKeyInRegion(key, region);
if (result != null) {
@@ -2350,6 +2396,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
get.addColumn(TABLE_FAMILY_BYTES, DATA_TABLE_NAME_BYTES);
get.addColumn(TABLE_FAMILY_BYTES, INDEX_STATE_BYTES);
get.addColumn(TABLE_FAMILY_BYTES, INDEX_DISABLE_TIMESTAMP_BYTES);
+ get.addColumn(TABLE_FAMILY_BYTES, ROW_KEY_ORDER_OPTIMIZABLE_BYTES);
Result currentResult = region.get(get);
if (currentResult.rawCells().length == 0) {
builder.setReturnCode(MetaDataProtos.MutationCode.TABLE_NOT_FOUND);
@@ -2360,6 +2407,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
Cell dataTableKV = currentResult.getColumnLatestCell(TABLE_FAMILY_BYTES, DATA_TABLE_NAME_BYTES);
Cell currentStateKV = currentResult.getColumnLatestCell(TABLE_FAMILY_BYTES, INDEX_STATE_BYTES);
Cell currentDisableTimeStamp = currentResult.getColumnLatestCell(TABLE_FAMILY_BYTES, INDEX_DISABLE_TIMESTAMP_BYTES);
+ boolean rowKeyOrderOptimizable = currentResult.getColumnLatestCell(TABLE_FAMILY_BYTES, ROW_KEY_ORDER_OPTIMIZABLE_BYTES) != null;
PIndexState currentState =
PIndexState.fromSerializedValue(currentStateKV.getValueArray()[currentStateKV
@@ -2418,6 +2466,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
INDEX_STATE_BYTES, timeStamp, Bytes.toBytes(newState.getSerializedValue())));
}
+ PTable returnTable = null;
if (currentState != newState) {
byte[] dataTableKey = null;
if(dataTableKV != null) {
@@ -2431,6 +2480,12 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
p.add(TABLE_FAMILY_BYTES, QueryConstants.EMPTY_COLUMN_BYTES, timeStamp, ByteUtil.EMPTY_BYTE_ARRAY);
tableMetadata.add(p);
}
+ boolean setRowKeyOrderOptimizableCell = newState == PIndexState.BUILDING && !rowKeyOrderOptimizable;
+ // We're starting a rebuild of the index, so add our rowKeyOrderOptimizable cell
+ // so that the row keys get generated using the new row key format
+ if (setRowKeyOrderOptimizableCell) {
+ UpgradeUtil.addRowKeyOrderOptimizableCell(tableMetadata, key, timeStamp);
+ }
region.mutateRowsWithLocks(tableMetadata, Collections.<byte[]> emptySet(), HConstants.NO_NONCE,
HConstants.NO_NONCE);
// Invalidate from cache
@@ -2439,12 +2494,18 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso
if(dataTableKey != null) {
metaDataCache.invalidate(new ImmutableBytesPtr(dataTableKey));
}
+ if (setRowKeyOrderOptimizableCell) {
+ returnTable = doGetTable(key, HConstants.LATEST_TIMESTAMP, rowLock);
+ }
}
// Get client timeStamp from mutations, since it may get updated by the
// mutateRowsWithLocks call
long currentTime = MetaDataUtil.getClientTimeStamp(tableMetadata);
builder.setReturnCode(MetaDataProtos.MutationCode.TABLE_ALREADY_EXISTS);
builder.setMutationTime(currentTime);
+ if (returnTable != null) {
+ builder.setTable(PTableImpl.toProto(returnTable));
+ }
done.run(builder.build());
return;
} finally {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
index d5cc486..788a342 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
@@ -28,6 +28,7 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -79,9 +80,12 @@ import org.apache.phoenix.schema.PColumn;
import org.apache.phoenix.schema.PRow;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.PTableImpl;
+import org.apache.phoenix.schema.RowKeySchema;
import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.ValueSchema.Field;
import org.apache.phoenix.schema.stats.StatisticsCollector;
import org.apache.phoenix.schema.tuple.MultiKeyValueTuple;
+import org.apache.phoenix.schema.types.PArrayDataType;
import org.apache.phoenix.schema.types.PDataType;
import org.apache.phoenix.util.ByteUtil;
import org.apache.phoenix.util.IndexUtil;
@@ -133,6 +137,7 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
}
Mutation[] mutationArray = new Mutation[mutations.size()];
// TODO: should we use the one that is all or none?
+ logger.warn("Committing bactch of " + mutations.size() + " mutations for " + region.getRegionInfo().getTable().getNameAsString());
region.batchMutate(mutations.toArray(mutationArray), HConstants.NO_NONCE, HConstants.NO_NONCE);
}
@@ -157,7 +162,6 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
@Override
protected RegionScanner doPostScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c, final Scan scan, final RegionScanner s) throws IOException {
- int offset = 0;
Region region = c.getEnvironment().getRegion();
long ts = scan.getTimeRange().getMax();
StatisticsCollector stats = null;
@@ -167,16 +171,33 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
// Let this throw, as this scan is being done for the sole purpose of collecting stats
stats = new StatisticsCollector(c.getEnvironment(), region.getRegionInfo().getTable().getNameAsString(), ts, gp_width_bytes, gp_per_region_bytes);
}
+ int offsetToBe = 0;
if (ScanUtil.isLocalIndex(scan)) {
/*
* For local indexes, we need to set an offset on row key expressions to skip
* the region start key.
*/
- offset = region.getRegionInfo().getStartKey().length != 0 ? region.getRegionInfo().getStartKey().length :
+ offsetToBe = region.getRegionInfo().getStartKey().length != 0 ? region.getRegionInfo().getStartKey().length :
region.getRegionInfo().getEndKey().length;
- ScanUtil.setRowKeyOffset(scan, offset);
+ ScanUtil.setRowKeyOffset(scan, offsetToBe);
}
+ final int offset = offsetToBe;
+ PTable projectedTable = null;
+ PTable writeToTable = null;
+ byte[][] values = null;
+ byte[] descRowKeyTableBytes = scan.getAttribute(UPGRADE_DESC_ROW_KEY);
+ boolean isDescRowKeyOrderUpgrade = descRowKeyTableBytes != null;
+ if (isDescRowKeyOrderUpgrade) {
+ logger.warn("Upgrading row key for " + region.getRegionInfo().getTable().getNameAsString());
+ projectedTable = deserializeTable(descRowKeyTableBytes);
+ try {
+ writeToTable = PTableImpl.makePTable(projectedTable, true);
+ } catch (SQLException e) {
+ ServerUtil.throwIOException("Upgrade failed", e); // Impossible
+ }
+ values = new byte[projectedTable.getPKColumns().size()][];
+ }
byte[] localIndexBytes = scan.getAttribute(LOCAL_INDEX_BUILD);
List<IndexMaintainer> indexMaintainers = localIndexBytes == null ? null : IndexMaintainer.deserialize(localIndexBytes);
List<Mutation> indexMutations = localIndexBytes == null ? Collections.<Mutation>emptyList() : Lists.<Mutation>newArrayListWithExpectedSize(1024);
@@ -184,22 +205,19 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
RegionScanner theScanner = s;
byte[] indexUUID = scan.getAttribute(PhoenixIndexCodec.INDEX_UUID);
- PTable projectedTable = null;
List<Expression> selectExpressions = null;
byte[] upsertSelectTable = scan.getAttribute(BaseScannerRegionObserver.UPSERT_SELECT_TABLE);
boolean isUpsert = false;
boolean isDelete = false;
byte[] deleteCQ = null;
byte[] deleteCF = null;
- byte[][] values = null;
byte[] emptyCF = null;
- ImmutableBytesWritable ptr = null;
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
if (upsertSelectTable != null) {
isUpsert = true;
projectedTable = deserializeTable(upsertSelectTable);
selectExpressions = deserializeExpressions(scan.getAttribute(BaseScannerRegionObserver.UPSERT_SELECT_EXPRS));
values = new byte[projectedTable.getPKColumns().size()][];
- ptr = new ImmutableBytesWritable();
} else {
byte[] isDeleteAgg = scan.getAttribute(BaseScannerRegionObserver.DELETE_AGG);
isDelete = isDeleteAgg != null && Bytes.compareTo(PDataType.TRUE_BYTES, isDeleteAgg) == 0;
@@ -209,9 +227,6 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
}
emptyCF = scan.getAttribute(BaseScannerRegionObserver.EMPTY_CF);
}
- if(localIndexBytes != null) {
- ptr = new ImmutableBytesWritable();
- }
TupleProjector tupleProjector = null;
Region dataRegion = null;
byte[][] viewConstants = null;
@@ -219,7 +234,7 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
boolean localIndexScan = ScanUtil.isLocalIndex(scan);
final TupleProjector p = TupleProjector.deserializeProjectorFromScan(scan);
final HashJoinInfo j = HashJoinInfo.deserializeHashJoinFromScan(scan);
- if ((localIndexScan && !isDelete) || (j == null && p != null)) {
+ if ((localIndexScan && !isDelete && !isDescRowKeyOrderUpgrade) || (j == null && p != null)) {
if (dataColumns != null) {
tupleProjector = IndexUtil.getTupleProjector(scan, dataColumns);
dataRegion = IndexUtil.getDataRegion(c.getEnvironment());
@@ -238,7 +253,7 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
int batchSize = 0;
List<Mutation> mutations = Collections.emptyList();
boolean buildLocalIndex = indexMaintainers != null && dataColumns==null && !localIndexScan;
- if (isDelete || isUpsert || (deleteCQ != null && deleteCF != null) || emptyCF != null || buildLocalIndex) {
+ if (isDescRowKeyOrderUpgrade || isDelete || isUpsert || (deleteCQ != null && deleteCF != null) || emptyCF != null || buildLocalIndex) {
// TODO: size better
mutations = Lists.newArrayListWithExpectedSize(1024);
batchSize = c.getEnvironment().getConfiguration().getInt(MUTATE_BATCH_SIZE_ATTRIB, QueryServicesOptions.DEFAULT_MUTATE_BATCH_SIZE);
@@ -270,7 +285,72 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
rowCount++;
result.setKeyValues(results);
try {
- if (buildLocalIndex) {
+ if (isDescRowKeyOrderUpgrade) {
+ Arrays.fill(values, null);
+ Cell firstKV = results.get(0);
+ RowKeySchema schema = projectedTable.getRowKeySchema();
+ int maxOffset = schema.iterator(firstKV.getRowArray(), firstKV.getRowOffset() + offset, firstKV.getRowLength(), ptr);
+ for (int i = 0; i < schema.getFieldCount(); i++) {
+ Boolean hasValue = schema.next(ptr, i, maxOffset);
+ if (hasValue == null) {
+ break;
+ }
+ Field field = schema.getField(i);
+ // Special case for re-writing DESC ARRAY, as the actual byte value needs to change in this case
+ if (field.getDataType().isArrayType() && field.getSortOrder() == SortOrder.DESC && !PArrayDataType.arrayBaseType(field.getDataType()).isFixedWidth()) {
+ field.getDataType().coerceBytes(ptr, null, field.getDataType(),
+ field.getMaxLength(), field.getScale(), field.getSortOrder(),
+ field.getMaxLength(), field.getScale(), field.getSortOrder(), true); // force to use correct separator byte
+ }
+ values[i] = ptr.copyBytes();
+ }
+ writeToTable.newKey(ptr, values);
+ if (Bytes.compareTo(
+ firstKV.getRowArray(), firstKV.getRowOffset() + offset, firstKV.getRowLength(),
+ ptr.get(),ptr.getOffset() + offset,ptr.getLength()) == 0) {
+ continue;
+ }
+ byte[] newRow = ByteUtil.copyKeyBytesIfNecessary(ptr);
+ if (offset > 0) { // for local indexes (prepend region start key)
+ byte[] newRowWithOffset = new byte[offset + newRow.length];
+ System.arraycopy(firstKV.getRowArray(), firstKV.getRowOffset(), newRowWithOffset, 0, offset);;
+ System.arraycopy(newRow, 0, newRowWithOffset, offset, newRow.length);
+ newRow = newRowWithOffset;
+ }
+ byte[] oldRow = Bytes.copy(firstKV.getRowArray(), firstKV.getRowOffset(), firstKV.getRowLength());
+ for (Cell cell : results) {
+ // Copy existing cell but with new row key
+ Cell newCell = new KeyValue(newRow, 0, newRow.length,
+ cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength(),
+ cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
+ cell.getTimestamp(), KeyValue.Type.codeToType(cell.getTypeByte()),
+ cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
+ switch (KeyValue.Type.codeToType(cell.getTypeByte())) {
+ case Put:
+ // If Put, point delete old Put
+ Delete del = new Delete(oldRow);
+ del.addDeleteMarker(new KeyValue(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(),
+ cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength(),
+ cell.getQualifierArray(), cell.getQualifierOffset(),
+ cell.getQualifierLength(), cell.getTimestamp(), KeyValue.Type.Delete,
+ ByteUtil.EMPTY_BYTE_ARRAY, 0, 0));
+ mutations.add(del);
+
+ Put put = new Put(newRow);
+ put.add(newCell);
+ mutations.add(put);
+ break;
+ case Delete:
+ case DeleteColumn:
+ case DeleteFamily:
+ case DeleteFamilyVersion:
+ Delete delete = new Delete(newRow);
+ delete.addDeleteMarker(newCell);
+ mutations.add(delete);
+ break;
+ }
+ }
+ } else if (buildLocalIndex) {
for (IndexMaintainer maintainer : indexMaintainers) {
if (!results.isEmpty()) {
result.getKey(ptr);
@@ -333,7 +413,7 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{
expression.getDataType(), expression.getMaxLength(),
expression.getScale(), expression.getSortOrder(),
column.getMaxLength(), column.getScale(),
- column.getSortOrder());
+ column.getSortOrder(), projectedTable.rowKeyOrderOptimizable());
byte[] bytes = ByteUtil.copyKeyBytesIfNecessary(ptr);
row.setValue(column, bytes);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java
index dd6e303..5b98b5e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java
@@ -3118,6 +3118,16 @@ public final class PTableProtos {
* <code>optional int32 baseColumnCount = 25;</code>
*/
int getBaseColumnCount();
+
+ // optional bool rowKeyOrderOptimizable = 26;
+ /**
+ * <code>optional bool rowKeyOrderOptimizable = 26;</code>
+ */
+ boolean hasRowKeyOrderOptimizable();
+ /**
+ * <code>optional bool rowKeyOrderOptimizable = 26;</code>
+ */
+ boolean getRowKeyOrderOptimizable();
}
/**
* Protobuf type {@code PTable}
@@ -3313,6 +3323,11 @@ public final class PTableProtos {
baseColumnCount_ = input.readInt32();
break;
}
+ case 208: {
+ bitField0_ |= 0x00200000;
+ rowKeyOrderOptimizable_ = input.readBool();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -3859,6 +3874,22 @@ public final class PTableProtos {
return baseColumnCount_;
}
+ // optional bool rowKeyOrderOptimizable = 26;
+ public static final int ROWKEYORDEROPTIMIZABLE_FIELD_NUMBER = 26;
+ private boolean rowKeyOrderOptimizable_;
+ /**
+ * <code>optional bool rowKeyOrderOptimizable = 26;</code>
+ */
+ public boolean hasRowKeyOrderOptimizable() {
+ return ((bitField0_ & 0x00200000) == 0x00200000);
+ }
+ /**
+ * <code>optional bool rowKeyOrderOptimizable = 26;</code>
+ */
+ public boolean getRowKeyOrderOptimizable() {
+ return rowKeyOrderOptimizable_;
+ }
+
private void initFields() {
schemaNameBytes_ = com.google.protobuf.ByteString.EMPTY;
tableNameBytes_ = com.google.protobuf.ByteString.EMPTY;
@@ -3885,6 +3916,7 @@ public final class PTableProtos {
statsTimeStamp_ = 0L;
storeNulls_ = false;
baseColumnCount_ = 0;
+ rowKeyOrderOptimizable_ = false;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -4027,6 +4059,9 @@ public final class PTableProtos {
if (((bitField0_ & 0x00100000) == 0x00100000)) {
output.writeInt32(25, baseColumnCount_);
}
+ if (((bitField0_ & 0x00200000) == 0x00200000)) {
+ output.writeBool(26, rowKeyOrderOptimizable_);
+ }
getUnknownFields().writeTo(output);
}
@@ -4141,6 +4176,10 @@ public final class PTableProtos {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(25, baseColumnCount_);
}
+ if (((bitField0_ & 0x00200000) == 0x00200000)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(26, rowKeyOrderOptimizable_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -4277,6 +4316,11 @@ public final class PTableProtos {
result = result && (getBaseColumnCount()
== other.getBaseColumnCount());
}
+ result = result && (hasRowKeyOrderOptimizable() == other.hasRowKeyOrderOptimizable());
+ if (hasRowKeyOrderOptimizable()) {
+ result = result && (getRowKeyOrderOptimizable()
+ == other.getRowKeyOrderOptimizable());
+ }
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@@ -4390,6 +4434,10 @@ public final class PTableProtos {
hash = (37 * hash) + BASECOLUMNCOUNT_FIELD_NUMBER;
hash = (53 * hash) + getBaseColumnCount();
}
+ if (hasRowKeyOrderOptimizable()) {
+ hash = (37 * hash) + ROWKEYORDEROPTIMIZABLE_FIELD_NUMBER;
+ hash = (53 * hash) + hashBoolean(getRowKeyOrderOptimizable());
+ }
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@@ -4564,6 +4612,8 @@ public final class PTableProtos {
bitField0_ = (bitField0_ & ~0x00800000);
baseColumnCount_ = 0;
bitField0_ = (bitField0_ & ~0x01000000);
+ rowKeyOrderOptimizable_ = false;
+ bitField0_ = (bitField0_ & ~0x02000000);
return this;
}
@@ -4708,6 +4758,10 @@ public final class PTableProtos {
to_bitField0_ |= 0x00100000;
}
result.baseColumnCount_ = baseColumnCount_;
+ if (((from_bitField0_ & 0x02000000) == 0x02000000)) {
+ to_bitField0_ |= 0x00200000;
+ }
+ result.rowKeyOrderOptimizable_ = rowKeyOrderOptimizable_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -4877,6 +4931,9 @@ public final class PTableProtos {
if (other.hasBaseColumnCount()) {
setBaseColumnCount(other.getBaseColumnCount());
}
+ if (other.hasRowKeyOrderOptimizable()) {
+ setRowKeyOrderOptimizable(other.getRowKeyOrderOptimizable());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -6514,6 +6571,39 @@ public final class PTableProtos {
return this;
}
+ // optional bool rowKeyOrderOptimizable = 26;
+ private boolean rowKeyOrderOptimizable_ ;
+ /**
+ * <code>optional bool rowKeyOrderOptimizable = 26;</code>
+ */
+ public boolean hasRowKeyOrderOptimizable() {
+ return ((bitField0_ & 0x02000000) == 0x02000000);
+ }
+ /**
+ * <code>optional bool rowKeyOrderOptimizable = 26;</code>
+ */
+ public boolean getRowKeyOrderOptimizable() {
+ return rowKeyOrderOptimizable_;
+ }
+ /**
+ * <code>optional bool rowKeyOrderOptimizable = 26;</code>
+ */
+ public Builder setRowKeyOrderOptimizable(boolean value) {
+ bitField0_ |= 0x02000000;
+ rowKeyOrderOptimizable_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bool rowKeyOrderOptimizable = 26;</code>
+ */
+ public Builder clearRowKeyOrderOptimizable() {
+ bitField0_ = (bitField0_ & ~0x02000000);
+ rowKeyOrderOptimizable_ = false;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:PTable)
}
@@ -6560,7 +6650,7 @@ public final class PTableProtos {
"values\030\002 \003(\014\022\033\n\023guidePostsByteCount\030\003 \001(" +
"\003\022\025\n\rkeyBytesCount\030\004 \001(\003\022\027\n\017guidePostsCo",
"unt\030\005 \001(\005\022!\n\013pGuidePosts\030\006 \001(\0132\014.PGuideP" +
- "osts\"\317\004\n\006PTable\022\027\n\017schemaNameBytes\030\001 \002(\014" +
+ "osts\"\357\004\n\006PTable\022\027\n\017schemaNameBytes\030\001 \002(\014" +
"\022\026\n\016tableNameBytes\030\002 \002(\014\022\036\n\ttableType\030\003 " +
"\002(\0162\013.PTableType\022\022\n\nindexState\030\004 \001(\t\022\026\n\016" +
"sequenceNumber\030\005 \002(\003\022\021\n\ttimeStamp\030\006 \002(\003\022" +
@@ -6574,11 +6664,12 @@ public final class PTableProtos {
"nt\030\022 \001(\014\022\025\n\rphysicalNames\030\023 \003(\014\022\020\n\010tenan" +
"tId\030\024 \001(\014\022\023\n\013viewIndexId\030\025 \001(\005\022\021\n\tindexT" +
"ype\030\026 \001(\014\022\026\n\016statsTimeStamp\030\027 \001(\003\022\022\n\nsto" +
- "reNulls\030\030 \001(\010\022\027\n\017baseColumnCount\030\031 \001(\005*A" +
- "\n\nPTableType\022\n\n\006SYSTEM\020\000\022\010\n\004USER\020\001\022\010\n\004VI" +
- "EW\020\002\022\t\n\005INDEX\020\003\022\010\n\004JOIN\020\004B@\n(org.apache." +
- "phoenix.coprocessor.generatedB\014PTablePro" +
- "tosH\001\210\001\001\240\001\001"
+ "reNulls\030\030 \001(\010\022\027\n\017baseColumnCount\030\031 \001(\005\022\036" +
+ "\n\026rowKeyOrderOptimizable\030\032 \001(\010*A\n\nPTable" +
+ "Type\022\n\n\006SYSTEM\020\000\022\010\n\004USER\020\001\022\010\n\004VIEW\020\002\022\t\n\005" +
+ "INDEX\020\003\022\010\n\004JOIN\020\004B@\n(org.apache.phoenix." +
+ "coprocessor.generatedB\014PTableProtosH\001\210\001\001",
+ "\240\001\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -6602,7 +6693,7 @@ public final class PTableProtos {
internal_static_PTable_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_PTable_descriptor,
- new java.lang.String[] { "SchemaNameBytes", "TableNameBytes", "TableType", "IndexState", "SequenceNumber", "TimeStamp", "PkNameBytes", "BucketNum", "Columns", "Indexes", "IsImmutableRows", "GuidePosts", "DataTableNameBytes", "DefaultFamilyName", "DisableWAL", "MultiTenant", "ViewType", "ViewStatement", "PhysicalNames", "TenantId", "ViewIndexId", "IndexType", "StatsTimeStamp", "StoreNulls", "BaseColumnCount", });
+ new java.lang.String[] { "SchemaNameBytes", "TableNameBytes", "TableType", "IndexState", "SequenceNumber", "TimeStamp", "PkNameBytes", "BucketNum", "Columns", "Indexes", "IsImmutableRows", "GuidePosts", "DataTableNameBytes", "DefaultFamilyName", "DisableWAL", "MultiTenant", "ViewType", "ViewStatement", "PhysicalNames", "TenantId", "ViewIndexId", "IndexType", "StatsTimeStamp", "StoreNulls", "BaseColumnCount", "RowKeyOrderOptimizable", });
return null;
}
};
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/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 195450c..acc3c86 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
@@ -249,6 +249,7 @@ public enum SQLExceptionCode {
NO_LOCAL_INDEXES(1054, "43A11", "Local secondary indexes are not supported for HBase versions " +
MetaDataUtil.decodeHBaseVersionAsString(PhoenixDatabaseMetaData.MIN_LOCAL_SI_VERSION_DISALLOW) + " through " + MetaDataUtil.decodeHBaseVersionAsString(PhoenixDatabaseMetaData.MAX_LOCAL_SI_VERSION_DISALLOW) + " inclusive."),
UNALLOWED_LOCAL_INDEXES(1055, "43A12", "Local secondary indexes are configured to not be allowed."),
+ DESC_VARBINARY_NOT_SUPPORTED(1056, "43A13", "Descending VARBINARY columns not supported"),
/** Sequence related */
SEQUENCE_ALREADY_EXIST(1200, "42Z00", "Sequence already exists.", new Factory() {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
index 5739e3e..11da1c9 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
@@ -32,6 +32,7 @@ import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.WritableUtils;
+import org.apache.htrace.TraceScope;
import org.apache.phoenix.compile.ExplainPlan;
import org.apache.phoenix.compile.FromCompiler;
import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
@@ -68,7 +69,6 @@ import org.apache.phoenix.util.LogUtil;
import org.apache.phoenix.util.SQLCloseable;
import org.apache.phoenix.util.SQLCloseables;
import org.apache.phoenix.util.ScanUtil;
-import org.apache.htrace.TraceScope;
import com.google.common.collect.Lists;
@@ -156,6 +156,7 @@ public abstract class BaseQueryPlan implements QueryPlan {
return iterator(Collections.<SQLCloseable>emptyList(), scanGrouper);
}
+ @Override
public final ResultIterator iterator() throws SQLException {
return iterator(Collections.<SQLCloseable>emptyList(), DefaultParallelScanGrouper.getInstance());
}
@@ -172,6 +173,7 @@ public abstract class BaseQueryPlan implements QueryPlan {
// Set miscellaneous scan attributes. This is the last chance to set them before we
// clone the scan for each parallelized chunk.
Scan scan = context.getScan();
+ PTable table = context.getCurrentTable().getTable();
if (OrderBy.REV_ROW_KEY_ORDER_BY.equals(orderBy)) {
ScanUtil.setReversed(scan);
@@ -190,8 +192,7 @@ public abstract class BaseQueryPlan implements QueryPlan {
PhoenixConnection connection = context.getConnection();
// set read consistency
- if (context.getCurrentTable() != null
- && context.getCurrentTable().getTable().getType() != PTableType.SYSTEM) {
+ if (table.getType() != PTableType.SYSTEM) {
scan.setConsistency(connection.getConsistency());
}
if (context.getScanTimeRange() == null) {
@@ -203,11 +204,12 @@ public abstract class BaseQueryPlan implements QueryPlan {
} else {
ScanUtil.setTimeRange(scan, context.getScanTimeRange());
}
+
ScanUtil.setTenantId(scan, connection.getTenantId() == null ? null : connection.getTenantId().getBytes());
String customAnnotations = LogUtil.customAnnotationsToString(connection);
ScanUtil.setCustomAnnotations(scan, customAnnotations == null ? null : customAnnotations.getBytes());
// Set local index related scan attributes.
- if (context.getCurrentTable().getTable().getIndexType() == IndexType.LOCAL) {
+ if (table.getIndexType() == IndexType.LOCAL) {
ScanUtil.setLocalIndex(scan);
Set<PColumn> dataColumns = context.getDataColumns();
// If any data columns to join back from data table are present then we set following attributes
@@ -221,8 +223,8 @@ public abstract class BaseQueryPlan implements QueryPlan {
KeyValueSchema schema = ProjectedColumnExpression.buildSchema(dataColumns);
// Set key value schema of the data columns.
serializeSchemaIntoScan(scan, schema);
- String parentSchema = context.getCurrentTable().getTable().getParentSchemaName().getString();
- String parentTable = context.getCurrentTable().getTable().getParentTableName().getString();
+ String parentSchema = table.getParentSchemaName().getString();
+ String parentTable = table.getParentTableName().getString();
final ParseNodeFactory FACTORY = new ParseNodeFactory();
TableRef dataTableRef =
FromCompiler.getResolver(
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java
new file mode 100644
index 0000000..40960e0
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/DescVarLengthFastByteComparisons.java
@@ -0,0 +1,219 @@
+/**
+ * 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.execute;
+
+import java.lang.reflect.Field;
+import java.nio.ByteOrder;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import sun.misc.Unsafe;
+
+import com.google.common.primitives.Longs;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Utility code to do optimized byte-array comparison.
+ * This is borrowed from org.apache.hadoop.io.FastByteComparisons
+ * which was borrowed and slightly modified from Guava's {@link UnsignedBytes}
+ * class to be able to compare arrays that start at non-zero offsets.
+ *
+ * The only difference is that we sort a smaller length bytes as *larger*
+ * than longer length bytes when all the bytes are the same.
+ */
+@SuppressWarnings("restriction")
+public class DescVarLengthFastByteComparisons {
+
+ private DescVarLengthFastByteComparisons() {}
+
+ /**
+ * Lexicographically compare two byte arrays.
+ */
+ public static int compareTo(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
+ return LexicographicalComparerHolder.BEST_COMPARER.compareTo(b1, s1, l1, b2, s2, l2);
+ }
+
+ private interface Comparer<T> {
+ abstract public int compareTo(T buffer1, int offset1, int length1, T buffer2, int offset2, int length2);
+ }
+
+ private static Comparer<byte[]> lexicographicalComparerJavaImpl() {
+ return LexicographicalComparerHolder.PureJavaComparer.INSTANCE;
+ }
+
+ /**
+ * Provides a lexicographical comparer implementation; either a Java implementation or a faster implementation based
+ * on {@link Unsafe}.
+ * <p>
+ * Uses reflection to gracefully fall back to the Java implementation if {@code Unsafe} isn't available.
+ */
+ private static class LexicographicalComparerHolder {
+ static final String UNSAFE_COMPARER_NAME = LexicographicalComparerHolder.class.getName() + "$UnsafeComparer";
+
+ static final Comparer<byte[]> BEST_COMPARER = getBestComparer();
+
+ /**
+ * Returns the Unsafe-using Comparer, or falls back to the pure-Java implementation if unable to do so.
+ */
+ static Comparer<byte[]> getBestComparer() {
+ try {
+ Class<?> theClass = Class.forName(UNSAFE_COMPARER_NAME);
+
+ // yes, UnsafeComparer does implement Comparer<byte[]>
+ @SuppressWarnings("unchecked")
+ Comparer<byte[]> comparer = (Comparer<byte[]>)theClass.getEnumConstants()[0];
+ return comparer;
+ } catch (Throwable t) { // ensure we really catch *everything*
+ return lexicographicalComparerJavaImpl();
+ }
+ }
+
+ private enum PureJavaComparer implements Comparer<byte[]> {
+ INSTANCE;
+
+ @Override
+ public int compareTo(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2) {
+ // Short circuit equal case
+ if (buffer1 == buffer2 && offset1 == offset2 && length1 == length2) { return 0; }
+ // Bring WritableComparator code local
+ int end1 = offset1 + length1;
+ int end2 = offset2 + length2;
+ for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) {
+ int a = (buffer1[i] & 0xff);
+ int b = (buffer2[j] & 0xff);
+ if (a != b) { return a - b; }
+ }
+ return length2 - length1;
+ }
+ }
+
+ @SuppressWarnings("unused")
+ // used via reflection
+ private enum UnsafeComparer implements Comparer<byte[]> {
+ INSTANCE;
+
+ static final Unsafe theUnsafe;
+
+ /** The offset to the first element in a byte array. */
+ static final int BYTE_ARRAY_BASE_OFFSET;
+
+ static {
+ theUnsafe = (Unsafe)AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ try {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ return f.get(null);
+ } catch (NoSuchFieldException e) {
+ // It doesn't matter what we throw;
+ // it's swallowed in getBestComparer().
+ throw new Error();
+ } catch (IllegalAccessException e) {
+ throw new Error();
+ }
+ }
+ });
+
+ BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
+
+ // sanity check - this should never fail
+ if (theUnsafe.arrayIndexScale(byte[].class) != 1) { throw new AssertionError(); }
+ }
+
+ static final boolean littleEndian = ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
+
+ /**
+ * Returns true if x1 is less than x2, when both values are treated as unsigned.
+ */
+ static boolean lessThanUnsigned(long x1, long x2) {
+ return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE);
+ }
+
+ /**
+ * Lexicographically compare two arrays.
+ *
+ * @param buffer1
+ * left operand
+ * @param buffer2
+ * right operand
+ * @param offset1
+ * Where to start comparing in the left buffer
+ * @param offset2
+ * Where to start comparing in the right buffer
+ * @param length1
+ * How much to compare from the left buffer
+ * @param length2
+ * How much to compare from the right buffer
+ * @return 0 if equal, < 0 if left is less than right, etc.
+ */
+ @Override
+ public int compareTo(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2) {
+ // Short circuit equal case
+ if (buffer1 == buffer2 && offset1 == offset2 && length1 == length2) { return 0; }
+ int minLength = Math.min(length1, length2);
+ int minWords = minLength / Longs.BYTES;
+ int offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;
+ int offset2Adj = offset2 + BYTE_ARRAY_BASE_OFFSET;
+
+ /*
+ * Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a time is no slower than comparing
+ * 4 bytes at a time even on 32-bit. On the other hand, it is substantially faster on 64-bit.
+ */
+ for (int i = 0; i < minWords * Longs.BYTES; i += Longs.BYTES) {
+ long lw = theUnsafe.getLong(buffer1, offset1Adj + (long)i);
+ long rw = theUnsafe.getLong(buffer2, offset2Adj + (long)i);
+ long diff = lw ^ rw;
+
+ if (diff != 0) {
+ if (!littleEndian) { return lessThanUnsigned(lw, rw) ? -1 : 1; }
+
+ // Use binary search
+ int n = 0;
+ int y;
+ int x = (int)diff;
+ if (x == 0) {
+ x = (int)(diff >>> 32);
+ n = 32;
+ }
+
+ y = x << 16;
+ if (y == 0) {
+ n += 16;
+ } else {
+ x = y;
+ }
+
+ y = x << 8;
+ if (y == 0) {
+ n += 8;
+ }
+ return (int)(((lw >>> n) & 0xFFL) - ((rw >>> n) & 0xFFL));
+ }
+ }
+
+ // The epilogue to cover the last (minLength % 8) elements.
+ for (int i = minWords * Longs.BYTES; i < minLength; i++) {
+ int result = UnsignedBytes.compare(buffer1[offset1 + i], buffer2[offset2 + i]);
+ if (result != 0) { return result; }
+ }
+ return length2 - length1;
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
index da581ce..d1b4a0e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
@@ -123,7 +123,7 @@ public class ArrayConstructorExpression extends BaseCompoundExpression {
if (position >= 0) position = elements.length;
if (!baseType.isFixedWidth()) {
// Double seperator byte to show end of the non null array
- PArrayDataType.writeEndSeperatorForVarLengthArray(oStream);
+ PArrayDataType.writeEndSeperatorForVarLengthArray(oStream, getSortOrder());
noOfElements = PArrayDataType.serailizeOffsetArrayIntoStream(oStream, byteStream, noOfElements,
offsetPos[offsetPos.length - 1], offsetPos);
PArrayDataType.serializeHeaderInfoIntoStream(oStream, noOfElements);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/expression/OrderByExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/OrderByExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/OrderByExpression.java
index 14bba68..456e58b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/OrderByExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/OrderByExpression.java
@@ -26,6 +26,7 @@ import java.io.IOException;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableUtils;
+import org.apache.phoenix.schema.SortOrder;
/**
* A container for a column that appears in ORDER BY clause.
@@ -83,7 +84,17 @@ public class OrderByExpression implements Writable {
@Override
public String toString() {
- return this.getExpression() + (isAscending ? "" : " DESC") + (isNullsLast ? " NULLS LAST" : "");
+ Expression e = this.getExpression();
+ boolean isNullsLast = this.isNullsLast;
+ boolean isAscending = this.isAscending;
+ // Flip back here based on sort order, as the compiler
+ // flips this, but we want to display the original back
+ // to the user.
+ if (e.getSortOrder() == SortOrder.DESC) {
+ isAscending = !isAscending;
+ isNullsLast = !isNullsLast;
+ }
+ return e + (isAscending ? "" : " DESC") + (isNullsLast ? " NULLS LAST" : "");
}
@Override
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java
index 940f909..481368c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java
@@ -184,7 +184,7 @@ public class RowValueConstructorExpression extends BaseCompoundExpression {
} else {
output.write(tempPtr.get(), tempPtr.getOffset(), tempPtr.getLength());
if (!childType.isFixedWidth()) {
- output.write(QueryConstants.SEPARATOR_BYTE);
+ output.write(SchemaUtil.getSeparatorByte(true, false, child));
}
if (previousCarryOver) {
previousCarryOver = !ByteUtil.previousKey(output.getBuffer(), output.size());
@@ -193,8 +193,12 @@ public class RowValueConstructorExpression extends BaseCompoundExpression {
}
int outputSize = output.size();
byte[] outputBytes = output.getBuffer();
+ // Don't remove trailing separator byte unless it's the one for ASC
+ // as otherwise we need it to ensure sort order is correct
for (int k = expressionCount -1 ;
- k >=0 && getChildren().get(k).getDataType() != null && !getChildren().get(k).getDataType().isFixedWidth() && outputBytes[outputSize-1] == QueryConstants.SEPARATOR_BYTE ; k--) {
+ k >=0 && getChildren().get(k).getDataType() != null
+ && !getChildren().get(k).getDataType().isFixedWidth()
+ && outputBytes[outputSize-1] == QueryConstants.SEPARATOR_BYTE ; k--) {
outputSize--;
}
ptr.set(outputBytes, 0, outputSize);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java
index d2b846a..77790b9 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java
@@ -50,6 +50,7 @@ public class ArrayConcatFunction extends ArrayModifierFunction {
if (!getLHSExpr().evaluate(tuple, ptr)|| ptr.getLength() == 0){
return false;
}
+ boolean isLHSRowKeyOrderOptimized = PArrayDataType.isRowKeyOrderOptimized(getLHSExpr().getDataType(), getLHSExpr().getSortOrder(), ptr);
int actualLengthOfArray1 = Math.abs(PArrayDataType.getArrayLength(ptr, getLHSBaseType(), getLHSExpr().getMaxLength()));
int lengthArray1 = ptr.getLength();
@@ -62,8 +63,13 @@ public class ArrayConcatFunction extends ArrayModifierFunction {
checkSizeCompatibility(ptr, getLHSExpr(), getLHSExpr().getDataType(), getRHSExpr(),getRHSExpr().getDataType());
- // Coerce array2 to array1 type
- coerceBytes(ptr, getLHSExpr(), getLHSExpr().getDataType(), getRHSExpr(),getRHSExpr().getDataType());
+ // FIXME: calling version of coerceBytes that takes into account the separator used by LHS
+ // If the RHS does not have the same separator, it'll be coerced to use it. It's unclear
+ // if we should do the same for all classes derived from the base class.
+ // Coerce RHS to LHS type
+ getLHSExpr().getDataType().coerceBytes(ptr, null, getRHSExpr().getDataType(), getRHSExpr().getMaxLength(),
+ getRHSExpr().getScale(), getRHSExpr().getSortOrder(), getLHSExpr().getMaxLength(),
+ getLHSExpr().getScale(), getLHSExpr().getSortOrder(), isLHSRowKeyOrderOptimized);
return modifierFunction(ptr, lengthArray1, offsetArray1, array1Bytes, getLHSBaseType(), actualLengthOfArray1, getMaxLength(), getLHSExpr());
}
@@ -72,6 +78,7 @@ public class ArrayConcatFunction extends ArrayModifierFunction {
byte[] array1Bytes, PDataType baseDataType, int actualLengthOfArray1, Integer maxLength,
Expression array1Exp) {
int actualLengthOfArray2 = Math.abs(PArrayDataType.getArrayLength(ptr, baseDataType, array1Exp.getMaxLength()));
+ // FIXME: concatArrays will be fine if it's copying the separator bytes, including the terminating bytes.
return PArrayDataType.concatArrays(ptr, len, offset, array1Bytes, baseDataType, actualLengthOfArray1, actualLengthOfArray2);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java
index 3177c29..9bd7372 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java
@@ -27,7 +27,8 @@ import org.apache.phoenix.expression.LiteralExpression;
import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.TypeMismatchException;
import org.apache.phoenix.schema.tuple.Tuple;
-import org.apache.phoenix.schema.types.*;
+import org.apache.phoenix.schema.types.PArrayDataType;
+import org.apache.phoenix.schema.types.PDataType;
public abstract class ArrayModifierFunction extends ScalarFunction {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java
index 9dfc8fc..eee03bf 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LpadFunction.java
@@ -22,12 +22,12 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.parse.FunctionParseNode.Argument;
import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.schema.types.PChar;
-import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.schema.SortOrder;
-import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.phoenix.util.StringUtil;
/**
@@ -146,7 +146,7 @@ public class LpadFunction extends ScalarFunction {
int numFillCharsPrepended = padLen % fillLen;
// byte length of the input string
- int strByteLength = getSubstringByteLength(ptr, ptr.getLength(), strSortOrder, isStrCharType);
+ int strByteLength = ptr.getLength();
// byte length of the fill string
int fillByteLength = getSubstringByteLength(fillPtr, fillPtr.getLength(), fillSortOrder, isFillCharType);
// byte length of the full fills to be prepended
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/expression/util/regex/JONIPattern.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/util/regex/JONIPattern.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/util/regex/JONIPattern.java
index 69f9eaf..af5bc2b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/util/regex/JONIPattern.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/util/regex/JONIPattern.java
@@ -158,8 +158,9 @@ public class JONIPattern extends AbstractBasePattern implements AbstractBaseSpli
private boolean
split(byte[] srcBytes, int srcOffset, int srcLen, ImmutableBytesWritable outPtr) {
+ SortOrder sortOrder = SortOrder.ASC;
PArrayDataTypeBytesArrayBuilder builder =
- new PArrayDataTypeBytesArrayBuilder(PVarchar.INSTANCE, SortOrder.ASC);
+ new PArrayDataTypeBytesArrayBuilder(PVarchar.INSTANCE, sortOrder);
int srcRange = srcOffset + srcLen;
Matcher matcher = pattern.matcher(srcBytes, 0, srcRange);
int cur = srcOffset;
@@ -191,7 +192,7 @@ public class JONIPattern extends AbstractBasePattern implements AbstractBaseSpli
break;
}
}
- byte[] bytes = builder.getBytesAndClose();
+ byte[] bytes = builder.getBytesAndClose(SortOrder.ASC);
if (bytes == null) return false;
outPtr.set(bytes);
return true;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java b/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
index 1923856..4dc888d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/filter/SkipScanFilter.java
@@ -37,7 +37,6 @@ import org.apache.hadoop.hbase.util.Writables;
import org.apache.hadoop.io.Writable;
import org.apache.phoenix.query.KeyRange;
import org.apache.phoenix.query.KeyRange.Bound;
-import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.RowKeySchema;
import org.apache.phoenix.util.ByteUtil;
import org.apache.phoenix.util.ScanUtil;
@@ -517,7 +516,7 @@ public class SkipScanFilter extends FilterBase implements Writable {
startKeyLength = length;
// Add separator byte if we're at the end of the buffer, since trailing separator bytes are stripped
if (ptr.getOffset() + ptr.getLength() == offset + length && i-1 > 0 && !schema.getField(i-1).getDataType().isFixedWidth()) {
- startKey[startKeyLength++] = QueryConstants.SEPARATOR_BYTE;
+ startKey[startKeyLength++] = SchemaUtil.getSeparatorByte(schema.rowKeyOrderOptimizable(), ptr.getLength()==0, schema.getField(i-1));
}
startKeyLength += setKey(Bound.LOWER, startKey, startKeyLength, i);
return length;
[14/50] [abbrv] phoenix git commit: PHOENIX-2058 Check for existence
and compatibility of columns being added in view
Posted by ma...@apache.org.
PHOENIX-2058 Check for existence and compatibility of columns being added in view
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/aa4c9003
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/aa4c9003
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/aa4c9003
Branch: refs/heads/calcite
Commit: aa4c9003d4bd4827718e0f37de8c270f94fd5694
Parents: 8c9a6b8
Author: Thomas D'Silva <td...@salesforce.com>
Authored: Wed Jul 8 15:54:17 2015 -0700
Committer: Thomas D'Silva <td...@salesforce.com>
Committed: Wed Jul 8 15:54:17 2015 -0700
----------------------------------------------------------------------
.../src/main/java/org/apache/phoenix/schema/MetaDataClient.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa4c9003/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 8a1c14b..d2d4338 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
@@ -2204,7 +2204,7 @@ public class MetaDataClient {
String familyName = null;
String msg = null;
// TODO: better to return error code
- if (result.getColumnName() != null && result.getColumnName() != null) {
+ if (result.getColumnName() != null) {
familyName = result.getFamilyName() == null ? null : Bytes.toString(result.getFamilyName());
columnName = Bytes.toString(result.getColumnName());
msg = "Cannot add/drop column referenced by VIEW";
[03/50] [abbrv] phoenix git commit: PHOENIX-922 Support SELECT
without a from clause
Posted by ma...@apache.org.
PHOENIX-922 Support SELECT without a from clause
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/df42fa13
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/df42fa13
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/df42fa13
Branch: refs/heads/calcite
Commit: df42fa13072df8a738e0bf2c2a22b58c512a9dcf
Parents: f579e72
Author: maryannxue <we...@intel.com>
Authored: Sat Jul 4 13:11:08 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Sat Jul 4 13:11:08 2015 -0400
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/SequenceIT.java | 27 ++++++
phoenix-core/src/main/antlr3/PhoenixSQL.g | 2 +-
.../apache/phoenix/compile/FromCompiler.java | 13 +--
.../phoenix/compile/ProjectionCompiler.java | 2 +-
.../apache/phoenix/compile/QueryCompiler.java | 9 +-
.../compile/TupleProjectionCompiler.java | 1 +
.../apache/phoenix/execute/BaseQueryPlan.java | 9 +-
.../phoenix/execute/EmptyTableQueryPlan.java | 96 ++++++++++++++++++++
.../apache/phoenix/parse/SelectStatement.java | 6 +-
.../org/apache/phoenix/schema/PTableImpl.java | 1 +
.../org/apache/phoenix/schema/TableRef.java | 2 +
.../phoenix/compile/QueryCompilerTest.java | 45 +++++++++
.../apache/phoenix/parse/QueryParserTest.java | 19 +---
13 files changed, 195 insertions(+), 37 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/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 6f2ec82..4273022 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
@@ -1242,5 +1242,32 @@ public class SequenceIT extends BaseClientManagedTimeIT {
assertEquals(4, rs.getLong(1));
assertFalse(rs.next());
}
+
+ @Test
+ public void testNoFromClause() throws Exception {
+ ResultSet rs;
+ nextConnection();
+ conn.createStatement().execute("CREATE SEQUENCE myseq START WITH 1 INCREMENT BY 1");
+ conn.createStatement().execute("CREATE SEQUENCE anotherseq START WITH 2 INCREMENT BY 3");
+ nextConnection();
+ rs = conn.createStatement().executeQuery("EXPLAIN SELECT NEXT VALUE FOR myseq");
+ assertEquals("CLIENT RESERVE VALUES FROM 1 SEQUENCE", QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery("SELECT NEXT VALUE FOR myseq");
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ rs = conn.createStatement().executeQuery("EXPLAIN SELECT CURRENT VALUE FOR myseq");
+ assertEquals("CLIENT RESERVE VALUES FROM 1 SEQUENCE", QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery("SELECT CURRENT VALUE FOR myseq");
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT NEXT VALUE FOR myseq, NEXT VALUE FOR anotherseq");
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertEquals(2, rs.getInt(2));
+ rs = conn.createStatement().executeQuery("SELECT CURRENT VALUE FOR myseq, NEXT VALUE FOR anotherseq");
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertEquals(5, rs.getInt(2));
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/antlr3/PhoenixSQL.g
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g
index 2a8d11b..69014a2 100644
--- a/phoenix-core/src/main/antlr3/PhoenixSQL.g
+++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g
@@ -629,7 +629,7 @@ single_select returns [SelectStatement ret]
@init{ contextStack.push(new ParseContext()); }
: SELECT (h=hintClause)?
(d=DISTINCT | ALL)? sel=select_list
- FROM from=parseFrom
+ (FROM from=parseFrom)?
(WHERE where=expression)?
(GROUP BY group=group_by)?
(HAVING having=expression)?
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
index bc753c9..30a2bb7 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
@@ -22,12 +22,9 @@ import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.client.HTableInterface;
import org.apache.phoenix.coprocessor.MetaDataProtocol;
@@ -37,13 +34,11 @@ import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.parse.AliasedNode;
import org.apache.phoenix.parse.BindTableNode;
import org.apache.phoenix.parse.ColumnDef;
-import org.apache.phoenix.parse.CreateFunctionStatement;
import org.apache.phoenix.parse.CreateTableStatement;
import org.apache.phoenix.parse.DMLStatement;
import org.apache.phoenix.parse.DerivedTableNode;
import org.apache.phoenix.parse.FamilyWildcardParseNode;
import org.apache.phoenix.parse.JoinTableNode;
-import org.apache.phoenix.parse.NamedNode;
import org.apache.phoenix.parse.NamedTableNode;
import org.apache.phoenix.parse.PFunction;
import org.apache.phoenix.parse.ParseNode;
@@ -106,7 +101,7 @@ public class FromCompiler {
@Override
public List<TableRef> getTables() {
- return Collections.emptyList();
+ return Collections.singletonList(TableRef.EMPTY_TABLE_REF);
}
@Override
@@ -117,16 +112,16 @@ public class FromCompiler {
@Override
public TableRef resolveTable(String schemaName, String tableName)
throws SQLException {
- throw new UnsupportedOperationException();
+ throw new TableNotFoundException(schemaName, tableName);
}
@Override
public ColumnRef resolveColumn(String schemaName, String tableName, String colName) throws SQLException {
- throw new UnsupportedOperationException();
+ throw new ColumnNotFoundException(schemaName, tableName, null, colName);
}
public PFunction resolveFunction(String functionName) throws SQLException {
- throw new UnsupportedOperationException();
+ throw new FunctionNotFoundException(functionName);
};
public boolean hasUDFs() {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java
index c39db09..915a55d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java
@@ -407,7 +407,7 @@ public class ProjectionCompiler {
String columnAlias = aliasedNode.getAlias() != null ? aliasedNode.getAlias() : SchemaUtil.normalizeIdentifier(aliasedNode.getNode().getAlias());
boolean isCaseSensitive = aliasedNode.getAlias() != null ? aliasedNode.isCaseSensitve() : (columnAlias != null ? SchemaUtil.isCaseSensitive(aliasedNode.getNode().getAlias()) : selectVisitor.isCaseSensitive);
String name = columnAlias == null ? expression.toString() : columnAlias;
- projectedColumns.add(new ExpressionProjector(name, tableRef.getTableAlias() == null ? table.getName().getString() : tableRef.getTableAlias(), expression, isCaseSensitive));
+ projectedColumns.add(new ExpressionProjector(name, tableRef.getTableAlias() == null ? (table.getName() == null ? "" : table.getName().getString()) : tableRef.getTableAlias(), expression, isCaseSensitive));
}
if(arrayKVFuncs.size() > 0 && arrayKVRefs.size() > 0) {
serailizeArrayIndexInformationAndSetInScan(context, arrayKVFuncs, arrayKVRefs);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
index 94ff075..ce3343e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
@@ -35,6 +35,7 @@ import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
import org.apache.phoenix.execute.AggregatePlan;
import org.apache.phoenix.execute.ClientAggregatePlan;
import org.apache.phoenix.execute.ClientScanPlan;
+import org.apache.phoenix.execute.EmptyTableQueryPlan;
import org.apache.phoenix.execute.HashJoinPlan;
import org.apache.phoenix.execute.HashJoinPlan.HashSubPlan;
import org.apache.phoenix.execute.HashJoinPlan.WhereClauseSubPlan;
@@ -555,9 +556,11 @@ public class QueryCompiler {
QueryPlan plan = innerPlan;
if (plan == null) {
ParallelIteratorFactory parallelIteratorFactory = asSubquery ? null : this.parallelIteratorFactory;
- plan = select.isAggregate() || select.isDistinct() ?
- new AggregatePlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory, groupBy, having)
- : new ScanPlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory, allowPageFilter);
+ plan = select.getFrom() == null ?
+ new EmptyTableQueryPlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory)
+ : (select.isAggregate() || select.isDistinct() ?
+ new AggregatePlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory, groupBy, having)
+ : new ScanPlan(context, select, tableRef, projector, limit, orderBy, parallelIteratorFactory, allowPageFilter));
}
if (!subqueries.isEmpty()) {
int count = subqueries.size();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
index 5114411..ee65280 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java
@@ -61,6 +61,7 @@ public class TupleProjectionCompiler {
Preconditions.checkArgument(!select.isJoin());
// Non-group-by or group-by aggregations will create its own projected result.
if (select.getInnerSelectStatement() != null
+ || select.getFrom() == null
|| select.isAggregate()
|| select.isDistinct()
|| (context.getResolver().getTables().get(0).getTable().getType() != PTableType.TABLE
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
index 37b73c0..5739e3e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
@@ -17,9 +17,6 @@
*/
package org.apache.phoenix.execute;
-import static org.apache.phoenix.compile.OrderByCompiler.OrderBy.FWD_ROW_KEY_ORDER_BY;
-import static org.apache.phoenix.compile.OrderByCompiler.OrderBy.REV_ROW_KEY_ORDER_BY;
-
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -56,8 +53,6 @@ import org.apache.phoenix.parse.FilterableStatement;
import org.apache.phoenix.parse.HintNode.Hint;
import org.apache.phoenix.parse.ParseNodeFactory;
import org.apache.phoenix.parse.TableName;
-import org.apache.phoenix.query.QueryServices;
-import org.apache.phoenix.query.QueryServicesOptions;
import org.apache.phoenix.schema.KeyValueSchema;
import org.apache.phoenix.schema.PColumn;
import org.apache.phoenix.schema.PName;
@@ -170,6 +165,10 @@ public abstract class BaseQueryPlan implements QueryPlan {
return ResultIterator.EMPTY_ITERATOR;
}
+ if (tableRef == TableRef.EMPTY_TABLE_REF) {
+ return newIterator(scanGrouper);
+ }
+
// Set miscellaneous scan attributes. This is the last chance to set them before we
// clone the scan for each parallelized chunk.
Scan scan = context.getScan();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/execute/EmptyTableQueryPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/EmptyTableQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/EmptyTableQueryPlan.java
new file mode 100644
index 0000000..fd55732
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/EmptyTableQueryPlan.java
@@ -0,0 +1,96 @@
+/*
+ * 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.execute;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
+import org.apache.phoenix.compile.OrderByCompiler.OrderBy;
+import org.apache.phoenix.compile.RowProjector;
+import org.apache.phoenix.compile.StatementContext;
+import org.apache.phoenix.iterate.ParallelIteratorFactory;
+import org.apache.phoenix.iterate.ParallelScanGrouper;
+import org.apache.phoenix.iterate.ResultIterator;
+import org.apache.phoenix.iterate.SequenceResultIterator;
+import org.apache.phoenix.parse.FilterableStatement;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.schema.TableRef;
+import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+public class EmptyTableQueryPlan extends BaseQueryPlan {
+
+ public EmptyTableQueryPlan(StatementContext context, FilterableStatement statement,
+ TableRef tableRef, RowProjector projection, Integer limit, OrderBy orderBy,
+ ParallelIteratorFactory parallelIteratorFactory) {
+ super(context, statement, tableRef, projection, context.getBindManager().getParameterMetaData(), limit, orderBy, GroupBy.EMPTY_GROUP_BY, parallelIteratorFactory);
+ }
+
+ @Override
+ public List<KeyRange> getSplits() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<List<Scan>> getScans() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean useRoundRobinIterator() throws SQLException {
+ return false;
+ }
+
+ @Override
+ protected ResultIterator newIterator(ParallelScanGrouper scanGrouper)
+ throws SQLException {
+ ResultIterator scanner = new ResultIterator() {
+ private boolean hasNext = true;
+
+ @Override
+ public void close() throws SQLException {
+ this.hasNext = false;
+ }
+
+ @Override
+ public Tuple next() throws SQLException {
+ if (hasNext) {
+ hasNext = false;
+ return new SingleKeyValueTuple(KeyValue.LOWESTKEY);
+ }
+ return null;
+ }
+
+ @Override
+ public void explain(List<String> planSteps) {
+ }
+
+ };
+
+ if (context.getSequenceManager().getSequenceCount() > 0) {
+ scanner = new SequenceResultIterator(scanner, context.getSequenceManager());
+ }
+
+ return scanner;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
index 362e98d..93c7364 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
@@ -124,8 +124,10 @@ public class SelectStatement implements FilterableStatement {
buf.append(',');
}
buf.setLength(buf.length()-1);
- buf.append(" FROM ");
- fromTable.toSQL(resolver, buf);
+ if (fromTable != null) {
+ buf.append(" FROM ");
+ fromTable.toSQL(resolver, buf);
+ }
if (where != null) {
buf.append(" WHERE ");
where.toSQL(resolver, buf);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
index 25b3e87..a947bfc 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java
@@ -130,6 +130,7 @@ public class PTableImpl implements PTable {
public PTableImpl() {
this.indexes = Collections.emptyList();
this.physicalNames = Collections.emptyList();
+ this.rowKeySchema = RowKeySchema.EMPTY_SCHEMA;
}
public PTableImpl(PName tenantId, String schemaName, String tableName, long timestamp, List<PColumnFamily> families) { // For base table of mapped VIEW
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java
index bd88770..78b00fa 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java
@@ -26,6 +26,8 @@ import org.apache.phoenix.util.SchemaUtil;
public class TableRef {
+ public static final TableRef EMPTY_TABLE_REF = new TableRef(new PTableImpl());
+
private PTable table;
private final String alias;
private final long upperBoundTimeStamp;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/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 7f15329..6e637b7 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
@@ -1900,5 +1900,50 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
conn.close();
}
}
+
+ @Test
+ public void testNoFromClauseSelect() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ ResultSet rs = conn.createStatement().executeQuery("SELECT 2 * 3 * 4, 5 + 1");
+ assertTrue(rs.next());
+ assertEquals(24, rs.getInt(1));
+ assertEquals(6, rs.getInt(2));
+ assertFalse(rs.next());
+
+ String query =
+ "SELECT 'a' AS col\n" +
+ "UNION ALL\n" +
+ "SELECT 'b' AS col\n" +
+ "UNION ALL\n" +
+ "SELECT 'c' AS col";
+ rs = conn.createStatement().executeQuery(query);
+ 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());
+
+ rs = conn.createStatement().executeQuery("SELECT * FROM (" + query + ")");
+ 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());
+ }
+
+
+ @Test
+ public void testFailNoFromClauseSelect() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ conn.createStatement().executeQuery("SELECT foo, bar");
+ fail("Should have got ColumnNotFoundException");
+ } catch (ColumnNotFoundException e) {
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/df42fa13/phoenix-core/src/test/java/org/apache/phoenix/parse/QueryParserTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/parse/QueryParserTest.java b/phoenix-core/src/test/java/org/apache/phoenix/parse/QueryParserTest.java
index eabd789..d651246 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/parse/QueryParserTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/parse/QueryParserTest.java
@@ -212,7 +212,7 @@ public class QueryParserTest {
parseQuery(sql);
fail();
} catch (SQLException e) {
- assertEquals(SQLExceptionCode.MISMATCHED_TOKEN.getErrorCode(), e.getErrorCode());
+ assertEquals(SQLExceptionCode.MISSING_TOKEN.getErrorCode(), e.getErrorCode());
}
}
@@ -348,7 +348,7 @@ public class QueryParserTest {
parseQuery(sql);
fail("Should have caught exception.");
} catch (SQLException e) {
- assertTrue(e.getMessage(), e.getMessage().contains("ERROR 602 (42P00): Syntax error. Missing \"FROM\" at line 1, column 16."));
+ assertTrue(e.getMessage(), e.getMessage().contains("ERROR 602 (42P00): Syntax error. Missing \"EOF\" at line 1, column 16."));
}
}
@@ -375,19 +375,6 @@ public class QueryParserTest {
}
@Test
- public void testParsingStatementWithMissingToken() throws Exception {
- try {
- String sql = ((
- "select a b\n" +
- "where e = d\n"));
- parseQuery(sql);
- fail("Should have caught exception.");
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.MISMATCHED_TOKEN.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
public void testParseCreateTableInlinePrimaryKeyWithOrder() throws Exception {
for (String order : new String[]{"asc", "desc"}) {
String s = "create table core.entity_history_archive (id char(15) primary key ${o})".replace("${o}", order);
@@ -612,7 +599,7 @@ public class QueryParserTest {
parseQuery(sql);
fail();
} catch (SQLException e) {
- assertEquals(SQLExceptionCode.MISMATCHED_TOKEN.getErrorCode(), e.getErrorCode());
+ assertEquals(SQLExceptionCode.MISSING_TOKEN.getErrorCode(), e.getErrorCode());
}
}
[17/50] [abbrv] phoenix git commit: PHOENIX-2103 : Pig tests aren't
dropping tables as expected between test runs
Posted by ma...@apache.org.
PHOENIX-2103 : Pig tests aren't dropping tables as expected between test runs
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/984e6222
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/984e6222
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/984e6222
Branch: refs/heads/calcite
Commit: 984e62223c8aa507e9c044cecfc7fc92ffa42522
Parents: 11bdb0e
Author: ravimagham <ra...@apache.org>
Authored: Thu Jul 9 20:20:32 2015 -0700
Committer: ravimagham <ra...@apache.org>
Committed: Thu Jul 9 20:20:32 2015 -0700
----------------------------------------------------------------------
.../phoenix/pig/PhoenixHBaseLoaderIT.java | 134 ++++++++-----------
1 file changed, 53 insertions(+), 81 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/984e6222/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
index 7fcf6ac..53a62ee 100644
--- a/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
+++ b/phoenix-pig/src/it/java/org/apache/phoenix/pig/PhoenixHBaseLoaderIT.java
@@ -19,9 +19,11 @@
*/
package org.apache.phoenix.pig;
-import static org.apache.phoenix.query.BaseTest.setUpConfigForMiniCluster;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.apache.phoenix.util.PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR;
+import static org.apache.phoenix.util.TestUtil.LOCALHOST;
import java.sql.Connection;
import java.sql.DriverManager;
@@ -35,18 +37,11 @@ import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.HBaseTestingUtility;
-import org.apache.phoenix.end2end.NeedsOwnMiniClusterTest;
-import org.apache.phoenix.jdbc.PhoenixDriver;
-import org.apache.phoenix.query.QueryServices;
-import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.end2end.BaseHBaseManagedTimeIT;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.TestUtil;
import org.apache.pig.ExecType;
import org.apache.pig.PigServer;
-import org.apache.pig.backend.hadoop.datastorage.ConfigurationUtil;
import org.apache.pig.builtin.mock.Storage;
import org.apache.pig.builtin.mock.Storage.Data;
import org.apache.pig.data.DataType;
@@ -54,20 +49,15 @@ import org.apache.pig.data.Tuple;
import org.apache.pig.impl.logicalLayer.schema.Schema;
import org.apache.pig.impl.logicalLayer.schema.Schema.FieldSchema;
import org.junit.After;
-import org.junit.AfterClass;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
import com.google.common.base.Preconditions;
/**
*
* Test class to run all the integration tests against a virtual map reduce cluster.
*/
-@Category(NeedsOwnMiniClusterTest.class)
-public class PhoenixHBaseLoaderIT {
+public class PhoenixHBaseLoaderIT extends BaseHBaseManagedTimeIT {
private static final Log LOG = LogFactory.getLog(PhoenixHBaseLoaderIT.class);
private static final String SCHEMA_NAME = "T";
@@ -76,32 +66,16 @@ public class PhoenixHBaseLoaderIT {
private static final String TABLE_FULL_NAME = SchemaUtil.getTableName(SCHEMA_NAME, TABLE_NAME);
private static final String CASE_SENSITIVE_TABLE_NAME = SchemaUtil.getEscapedArgument("a");
private static final String CASE_SENSITIVE_TABLE_FULL_NAME = SchemaUtil.getTableName(SCHEMA_NAME,CASE_SENSITIVE_TABLE_NAME);
- private static HBaseTestingUtility hbaseTestUtil;
- private static String zkQuorum;
- private static Connection conn;
- private static PigServer pigServer;
- private static Configuration conf;
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- hbaseTestUtil = new HBaseTestingUtility();
- conf = hbaseTestUtil.getConfiguration();
- setUpConfigForMiniCluster(conf);
- conf.set(QueryServices.DROP_METADATA_ATTRIB, Boolean.toString(true));
- hbaseTestUtil.startMiniCluster();
+ private String zkQuorum;
+ private Connection conn;
+ private PigServer pigServer;
- Class.forName(PhoenixDriver.class.getName());
- zkQuorum = "localhost:" + hbaseTestUtil.getZkCluster().getClientPort();
- Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);
- props.put(QueryServices.DROP_METADATA_ATTRIB, Boolean.toString(true));
- conn = DriverManager.getConnection(PhoenixRuntime.JDBC_PROTOCOL +
- PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR + zkQuorum,props);
- }
-
@Before
public void setUp() throws Exception {
- pigServer = new PigServer(ExecType.LOCAL,
- ConfigurationUtil.toProperties(conf));
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ zkQuorum = LOCALHOST + JDBC_PROTOCOL_SEPARATOR + getZKClientPort(getTestClusterConfig());
+ pigServer = new PigServer(ExecType.LOCAL, getTestClusterConfig());
}
/**
@@ -110,13 +84,14 @@ public class PhoenixHBaseLoaderIT {
*/
@Test
public void testSchemaForTable() throws Exception {
+ final String TABLE = "TABLE1";
final String ddl = String.format("CREATE TABLE %s "
+ " (a_string varchar not null, a_binary varbinary not null, a_integer integer, cf1.a_float float"
- + " CONSTRAINT pk PRIMARY KEY (a_string, a_binary))\n", TABLE_FULL_NAME);
+ + " CONSTRAINT pk PRIMARY KEY (a_string, a_binary))\n", TABLE);
conn.createStatement().execute(ddl);
-
+ conn.commit();
pigServer.registerQuery(String.format(
- "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", TABLE_FULL_NAME,
+ "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", TABLE,
zkQuorum));
final Schema schema = pigServer.dumpSchema("A");
@@ -140,15 +115,15 @@ public class PhoenixHBaseLoaderIT {
public void testSchemaForTableWithSpecificColumns() throws Exception {
//create the table
- final String ddl = "CREATE TABLE " + TABLE_FULL_NAME
+ final String TABLE = "TABLE2";
+ final String ddl = "CREATE TABLE " + TABLE
+ " (ID INTEGER NOT NULL PRIMARY KEY,NAME VARCHAR, AGE INTEGER) ";
conn.createStatement().execute(ddl);
-
final String selectColumns = "ID,NAME";
pigServer.registerQuery(String.format(
"A = load 'hbase://table/%s/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');",
- TABLE_FULL_NAME, selectColumns, zkQuorum));
+ TABLE, selectColumns, zkQuorum));
Schema schema = pigServer.dumpSchema("A");
List<FieldSchema> fields = schema.getFields();
@@ -157,7 +132,6 @@ public class PhoenixHBaseLoaderIT {
assertTrue(fields.get(0).type == DataType.INTEGER);
assertTrue(fields.get(1).alias.equalsIgnoreCase("NAME"));
assertTrue(fields.get(1).type == DataType.CHARARRAY);
-
}
/**
@@ -168,15 +142,16 @@ public class PhoenixHBaseLoaderIT {
public void testSchemaForQuery() throws Exception {
//create the table.
- String ddl = String.format("CREATE TABLE " + TABLE_FULL_NAME +
+ final String TABLE = "TABLE3";
+ String ddl = String.format("CREATE TABLE " + TABLE +
" (A_STRING VARCHAR NOT NULL, A_DECIMAL DECIMAL NOT NULL, CF1.A_INTEGER INTEGER, CF2.A_DOUBLE DOUBLE"
- + " CONSTRAINT pk PRIMARY KEY (A_STRING, A_DECIMAL))\n", TABLE_FULL_NAME);
+ + " CONSTRAINT pk PRIMARY KEY (A_STRING, A_DECIMAL))\n", TABLE);
conn.createStatement().execute(ddl);
-
+
//sql query for LOAD
- final String sqlQuery = "SELECT A_STRING,CF1.A_INTEGER,CF2.A_DOUBLE FROM " + TABLE_FULL_NAME;
+ final String sqlQuery = "SELECT A_STRING,CF1.A_INTEGER,CF2.A_DOUBLE FROM " + TABLE;
pigServer.registerQuery(String.format(
"A = load 'hbase://query/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');",
sqlQuery, zkQuorum));
@@ -201,13 +176,14 @@ public class PhoenixHBaseLoaderIT {
public void testSchemaForTableWithAlias() throws Exception {
//create the table.
- String ddl = "CREATE TABLE " + TABLE_FULL_NAME
+ final String TABLE = "S.TABLE4";
+ String ddl = "CREATE TABLE " + TABLE
+ " (A_STRING VARCHAR NOT NULL, A_DECIMAL DECIMAL NOT NULL, CF1.A_INTEGER INTEGER, CF2.A_DOUBLE DOUBLE"
+ " CONSTRAINT pk PRIMARY KEY (A_STRING, A_DECIMAL)) \n";
conn.createStatement().execute(ddl);
-
+
//select query given as part of LOAD.
- final String sqlQuery = "SELECT A_STRING,A_DECIMAL,CF1.A_INTEGER,CF2.A_DOUBLE FROM " + TABLE_FULL_NAME;
+ final String sqlQuery = "SELECT A_STRING,A_DECIMAL,CF1.A_INTEGER,CF2.A_DOUBLE FROM " + TABLE;
LOG.info(String.format("Generated SQL Query [%s]",sqlQuery));
@@ -317,13 +293,14 @@ public class PhoenixHBaseLoaderIT {
public void testForNonPKSQLQuery() throws Exception {
//create the table
- String ddl = "CREATE TABLE " + TABLE_FULL_NAME
+ final String TABLE = "TABLE5";
+ String ddl = "CREATE TABLE " + TABLE
+ " ( ID VARCHAR PRIMARY KEY, FOO VARCHAR, BAR INTEGER, BAZ UNSIGNED_INT)";
conn.createStatement().execute(ddl);
//upsert data.
- final String dml = "UPSERT INTO " + TABLE_FULL_NAME + " VALUES(?,?,?,?) ";
+ final String dml = "UPSERT INTO " + TABLE + " VALUES(?,?,?,?) ";
PreparedStatement stmt = conn.prepareStatement(dml);
stmt.setString(1, "a");
stmt.setString(2, "a");
@@ -339,7 +316,7 @@ public class PhoenixHBaseLoaderIT {
conn.commit();
//sql query
- final String sqlQuery = String.format(" SELECT FOO, BAZ FROM %s WHERE BAR = -1 " , TABLE_FULL_NAME);
+ final String sqlQuery = String.format(" SELECT FOO, BAZ FROM %s WHERE BAR = -1 " , TABLE);
pigServer.registerQuery(String.format(
"A = load 'hbase://query/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", sqlQuery,
@@ -372,13 +349,14 @@ public class PhoenixHBaseLoaderIT {
public void testGroupingOfDataForTable() throws Exception {
//create the table
- String ddl = "CREATE TABLE " + TABLE_FULL_NAME
+ final String TABLE = "TABLE6";
+ String ddl = "CREATE TABLE " + TABLE
+ " (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR, AGE INTEGER, SAL INTEGER) ";
conn.createStatement().execute(ddl);
//prepare data with 10 rows having age 25 and the other 30.
- final String dml = "UPSERT INTO " + TABLE_FULL_NAME + " VALUES(?,?,?,?)";
+ final String dml = "UPSERT INTO " + TABLE + " VALUES(?,?,?,?)";
PreparedStatement stmt = conn.prepareStatement(dml);
int rows = 20;
int j = 0, k = 0;
@@ -406,7 +384,7 @@ public class PhoenixHBaseLoaderIT {
//load data and filter rows whose age is > 25
pigServer.setBatchOn();
pigServer.registerQuery(String.format(
- "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", TABLE_FULL_NAME,
+ "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", TABLE,
zkQuorum));
pigServer.registerQuery("B = GROUP A BY AGE;");
@@ -426,18 +404,19 @@ public class PhoenixHBaseLoaderIT {
public void testLoadAndStore() throws Exception {
//create the tables
- final String sourceTableddl = "CREATE TABLE " + TABLE_FULL_NAME
+ final String TABLE = "TABLE7";
+ final String sourceTableddl = "CREATE TABLE " + TABLE
+ " (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR, AGE INTEGER, SAL INTEGER) ";
- final String targetTable = "AGGREGATE";
- final String targetTableddl = "CREATE TABLE " + targetTable
+ final String targetTable = "AGGREGATE";
+ final String targetTableddl = "CREATE TABLE " + targetTable
+ "(AGE INTEGER NOT NULL PRIMARY KEY , MIN_SAL INTEGER , MAX_SAL INTEGER) ";
conn.createStatement().execute(sourceTableddl);
conn.createStatement().execute(targetTableddl);
//prepare data with 10 rows having age 25 and the other 30.
- final String dml = "UPSERT INTO " + TABLE_FULL_NAME + " VALUES(?,?,?,?)";
+ final String dml = "UPSERT INTO " + TABLE + " VALUES(?,?,?,?)";
PreparedStatement stmt = conn.prepareStatement(dml);
int rows = 20;
int j = 0, k = 0;
@@ -460,7 +439,7 @@ public class PhoenixHBaseLoaderIT {
//load data and filter rows whose age is > 25
pigServer.setBatchOn();
pigServer.registerQuery(String.format(
- "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", TABLE_FULL_NAME,
+ "A = load 'hbase://table/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", TABLE,
zkQuorum));
pigServer.registerQuery("B = GROUP A BY AGE;");
@@ -491,7 +470,8 @@ public class PhoenixHBaseLoaderIT {
public void testDataForSQLQueryWithSequences() throws Exception {
//create the table
- String ddl = "CREATE TABLE " + TABLE_FULL_NAME
+ final String TABLE = "TABLE8";
+ String ddl = "CREATE TABLE " + TABLE
+ " (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR, AGE INTEGER) ";
conn.createStatement().execute(ddl);
@@ -501,7 +481,7 @@ public class PhoenixHBaseLoaderIT {
conn.createStatement().execute(sequenceDdl);
//prepare data with 10 rows having age 25 and the other 30.
- final String dml = "UPSERT INTO " + TABLE_FULL_NAME + " VALUES(?,?,?)";
+ final String dml = "UPSERT INTO " + TABLE + " VALUES(?,?,?)";
PreparedStatement stmt = conn.prepareStatement(dml);
int rows = 20;
for(int i = 0 ; i < rows; i++) {
@@ -513,7 +493,7 @@ public class PhoenixHBaseLoaderIT {
conn.commit();
//sql query load data and filter rows whose age is > 25
- final String sqlQuery = " SELECT NEXT VALUE FOR my_sequence AS my_seq,ID,NAME,AGE FROM " + TABLE_FULL_NAME + " WHERE AGE > 25";
+ final String sqlQuery = " SELECT NEXT VALUE FOR my_sequence AS my_seq,ID,NAME,AGE FROM " + TABLE + " WHERE AGE > 25";
pigServer.registerQuery(String.format(
"A = load 'hbase://query/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", sqlQuery,
zkQuorum));
@@ -532,12 +512,13 @@ public class PhoenixHBaseLoaderIT {
public void testDataForSQLQueryWithFunctions() throws Exception {
//create the table
- String ddl = "CREATE TABLE " + TABLE_FULL_NAME
+ final String TABLE = "TABLE9";
+ String ddl = "CREATE TABLE " + TABLE
+ " (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR) ";
conn.createStatement().execute(ddl);
- final String dml = "UPSERT INTO " + TABLE_FULL_NAME + " VALUES(?,?)";
+ final String dml = "UPSERT INTO " + TABLE + " VALUES(?,?)";
PreparedStatement stmt = conn.prepareStatement(dml);
int rows = 20;
for(int i = 0 ; i < rows; i++) {
@@ -548,7 +529,7 @@ public class PhoenixHBaseLoaderIT {
conn.commit();
//sql query
- final String sqlQuery = " SELECT UPPER(NAME) AS n FROM " + TABLE_FULL_NAME + " ORDER BY ID" ;
+ final String sqlQuery = " SELECT UPPER(NAME) AS n FROM " + TABLE + " ORDER BY ID" ;
pigServer.registerQuery(String.format(
"A = load 'hbase://query/%s' using " + PhoenixHBaseLoader.class.getName() + "('%s');", sqlQuery,
@@ -604,23 +585,14 @@ public class PhoenixHBaseLoaderIT {
@After
public void tearDown() throws Exception {
- dropTable(TABLE_FULL_NAME);
- dropTable(CASE_SENSITIVE_TABLE_FULL_NAME);
+ if(conn != null) {
+ conn.close();
+ }
pigServer.shutdown();
}
-
private void dropTable(String tableFullName) throws SQLException {
Preconditions.checkNotNull(conn);
conn.createStatement().execute(String.format("DROP TABLE IF EXISTS %s",tableFullName));
}
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- try {
- conn.close();
- } finally {
- hbaseTestUtil.shutdownMiniCluster();
- }
- }
}
\ No newline at end of file
[30/50] [abbrv] phoenix git commit: PHOENIX-2067 Sort order incorrect
for variable length DESC columns
Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDateArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDateArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDateArray.java
index 764401c..a07418c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDateArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDateArray.java
@@ -17,93 +17,78 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.phoenix.schema.SortOrder;
-
-import java.sql.Types;
import java.sql.Date;
-public class PDateArray extends PArrayDataType<Date[]> {
-
- public static final PDateArray INSTANCE = new PDateArray();
-
- private PDateArray() {
- super("DATE ARRAY", PDataType.ARRAY_TYPE_BASE + PDate.INSTANCE.getSqlType(), PhoenixArray.class,
- null, 40);
- }
+import org.apache.phoenix.schema.SortOrder;
- @Override
- public boolean isArrayType() {
- return true;
- }
+public class PDateArray extends PArrayDataType<Date[]> {
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PDateArray INSTANCE = new PDateArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PDateArray() {
+ super("DATE ARRAY", PDataType.ARRAY_TYPE_BASE + PDate.INSTANCE.getSqlType(), PhoenixArray.class,
+ null, 40);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PDate.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
- return toObject(bytes, offset, length, PDate.INSTANCE, sortOrder, maxLength, scale,
- PDate.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PDate.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] dateArr = (Object[]) pArr.array;
- for (Object i : dateArr) {
- if (!super.isCoercibleTo(PDate.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
+ return toObject(bytes, offset, length, PDate.INSTANCE, sortOrder, maxLength, scale,
+ PDate.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale,SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] dateArr = (Object[]) pArr.array;
+ for (Object i : dateArr) {
+ if (!super.isCoercibleTo(PDate.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PDate.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PDate.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java
index 6874ac3..101546a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java
@@ -17,94 +17,72 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.phoenix.schema.SortOrder;
-
import java.math.BigDecimal;
-import java.sql.Types;
-
-public class PDecimalArray extends PArrayDataType<BigDecimal[]> {
-
- public static final PDecimalArray INSTANCE = new PDecimalArray();
- private PDecimalArray() {
- super("DECIMAL ARRAY", PDataType.ARRAY_TYPE_BASE + PDecimal.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 35);
- }
+import org.apache.phoenix.schema.SortOrder;
- @Override
- public boolean isArrayType() {
- return true;
- }
+public class PDecimalArray extends PArrayDataType<BigDecimal[]> {
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PDecimalArray INSTANCE = new PDecimalArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PDecimalArray() {
+ super("DECIMAL ARRAY", PDataType.ARRAY_TYPE_BASE + PDecimal.INSTANCE.getSqlType(), PhoenixArray.class, null, 35);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PDecimal.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PDecimal.INSTANCE, sortOrder, maxLength, scale,
- PDecimal.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PDecimal.INSTANCE, sortOrder);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder,
+ Integer maxLength, Integer scale) {
+ return toObject(bytes, offset, length, PDecimal.INSTANCE, sortOrder, maxLength, scale, PDecimal.INSTANCE);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] decimalArr = (Object[]) pArr.array;
- for (Object i : decimalArr) {
- if (!super.isCoercibleTo(PDecimal.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) { return true; }
+ PhoenixArray pArr = (PhoenixArray)value;
+ Object[] decimalArr = (Object[])pArr.array;
+ for (Object i : decimalArr) {
+ if (!super.isCoercibleTo(PDecimal.INSTANCE, i)) { return false; }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PDecimal.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PDecimal.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java
index 7ecec61..d585229 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java
@@ -17,92 +17,76 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PDoubleArray extends PArrayDataType<double[]> {
- public static final PDoubleArray INSTANCE = new PDoubleArray();
-
- private PDoubleArray() {
- super("DOUBLE ARRAY", PDataType.ARRAY_TYPE_BASE + PDouble.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 34);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PDoubleArray INSTANCE = new PDoubleArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PDoubleArray() {
+ super("DOUBLE ARRAY", PDataType.ARRAY_TYPE_BASE + PDouble.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 34);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PDouble.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
- return toObject(bytes, offset, length, PDouble.INSTANCE, sortOrder, maxLength, scale,
- PDouble.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PDouble.INSTANCE, sortOrder);
}
- PhoenixArray.PrimitiveDoublePhoenixArray pArr = (PhoenixArray.PrimitiveDoublePhoenixArray) value;
- double[] doubleArr = (double[]) pArr.array;
- for (double i : doubleArr) {
- if (!super.isCoercibleTo(PDouble.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
+ return toObject(bytes, offset, length, PDouble.INSTANCE, sortOrder, maxLength, scale,
+ PDouble.INSTANCE);
}
- return true;
- }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray.PrimitiveDoublePhoenixArray pArr = (PhoenixArray.PrimitiveDoublePhoenixArray) value;
+ double[] doubleArr = (double[]) pArr.array;
+ for (double i : doubleArr) {
+ if (!super.isCoercibleTo(PDouble.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PDouble.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PDouble.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java
index 5e8ddb3..6005c3e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PFloatArray extends PArrayDataType<float[]> {
- public static final PFloatArray INSTANCE = new PFloatArray();
-
- private PFloatArray() {
- super("FLOAT ARRAY", PDataType.ARRAY_TYPE_BASE + PFloat.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 33);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PFloatArray INSTANCE = new PFloatArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PFloatArray() {
+ super("FLOAT ARRAY", PDataType.ARRAY_TYPE_BASE + PFloat.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 33);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PFloat.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PFloat.INSTANCE, sortOrder, maxLength, scale,
- PFloat.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PFloat.INSTANCE, sortOrder);
}
- PhoenixArray.PrimitiveFloatPhoenixArray pArr = (PhoenixArray.PrimitiveFloatPhoenixArray) value;
- float[] floatArr = (float[]) pArr.array;
- for (float i : floatArr) {
- if (!super.isCoercibleTo(PFloat.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PFloat.INSTANCE, sortOrder, maxLength, scale,
+ PFloat.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray.PrimitiveFloatPhoenixArray pArr = (PhoenixArray.PrimitiveFloatPhoenixArray) value;
+ float[] floatArr = (float[]) pArr.array;
+ for (float i : floatArr) {
+ if (!super.isCoercibleTo(PFloat.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PFloat.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PFloat.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java
index 28a5c4c..b317cfe 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PIntegerArray extends PArrayDataType<int[]> {
- public static final PIntegerArray INSTANCE = new PIntegerArray();
-
- private PIntegerArray() {
- super("INTEGER ARRAY", PDataType.ARRAY_TYPE_BASE + PInteger.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 24);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PIntegerArray INSTANCE = new PIntegerArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PIntegerArray() {
+ super("INTEGER ARRAY", PDataType.ARRAY_TYPE_BASE + PInteger.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 24);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PInteger.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PInteger.INSTANCE, sortOrder, maxLength, scale,
- PInteger.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PInteger.INSTANCE, sortOrder);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PInteger.INSTANCE, sortOrder, maxLength, scale,
+ PInteger.INSTANCE);
}
- PhoenixArray.PrimitiveIntPhoenixArray pArr = (PhoenixArray.PrimitiveIntPhoenixArray) value;
- int[] intArr = (int[]) pArr.array;
- for (int i : intArr) {
- if (!super.isCoercibleTo(PInteger.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray.PrimitiveIntPhoenixArray pArr = (PhoenixArray.PrimitiveIntPhoenixArray) value;
+ int[] intArr = (int[]) pArr.array;
+ for (int i : intArr) {
+ if (!super.isCoercibleTo(PInteger.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PInteger.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PInteger.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java
index 0670792..aef6437 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PLongArray extends PArrayDataType<long[]> {
- public static final PLongArray INSTANCE = new PLongArray();
-
- private PLongArray() {
- super("BIGINT ARRAY", PDataType.ARRAY_TYPE_BASE + PLong.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 30);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PLongArray INSTANCE = new PLongArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PLongArray() {
+ super("BIGINT ARRAY", PDataType.ARRAY_TYPE_BASE + PLong.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 30);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PLong.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PLong.INSTANCE, sortOrder, maxLength, scale,
- PLong.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PLong.INSTANCE, sortOrder);
}
- PhoenixArray.PrimitiveLongPhoenixArray pArr = (PhoenixArray.PrimitiveLongPhoenixArray) value;
- long[] longArr = (long[]) pArr.array;
- for (long i : longArr) {
- if (!super.isCoercibleTo(PLong.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PLong.INSTANCE, sortOrder, maxLength, scale,
+ PLong.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray.PrimitiveLongPhoenixArray pArr = (PhoenixArray.PrimitiveLongPhoenixArray) value;
+ long[] longArr = (long[]) pArr.array;
+ for (long i : longArr) {
+ if (!super.isCoercibleTo(PLong.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PLong.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PLong.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallintArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallintArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallintArray.java
index 98da723..aea4384 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallintArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallintArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PSmallintArray extends PArrayDataType<short[]> {
- public static final PSmallintArray INSTANCE = new PSmallintArray();
-
- private PSmallintArray() {
- super("SMALLINT ARRAY", PDataType.ARRAY_TYPE_BASE + PSmallint.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 31);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PSmallintArray INSTANCE = new PSmallintArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PSmallintArray() {
+ super("SMALLINT ARRAY", PDataType.ARRAY_TYPE_BASE + PSmallint.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 31);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PSmallint.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PSmallint.INSTANCE, sortOrder, maxLength, scale,
- PSmallint.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PSmallint.INSTANCE, sortOrder);
}
- PhoenixArray.PrimitiveShortPhoenixArray pArr = (PhoenixArray.PrimitiveShortPhoenixArray) value;
- short[] shortArr = (short[]) pArr.array;
- for (short i : shortArr) {
- if (!super.isCoercibleTo(PSmallint.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PSmallint.INSTANCE, sortOrder, maxLength, scale,
+ PSmallint.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray.PrimitiveShortPhoenixArray pArr = (PhoenixArray.PrimitiveShortPhoenixArray) value;
+ short[] shortArr = (short[]) pArr.array;
+ for (short i : shortArr) {
+ if (!super.isCoercibleTo(PSmallint.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PSmallint.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PSmallint.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimeArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimeArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimeArray.java
index e0a7655..c19fd71 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimeArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimeArray.java
@@ -17,94 +17,79 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.phoenix.schema.SortOrder;
-
import java.sql.Time;
-import java.sql.Types;
-
-public class PTimeArray extends PArrayDataType<Time[]> {
-
- public static final PTimeArray INSTANCE = new PTimeArray();
- private PTimeArray() {
- super("TIME ARRAY", PDataType.ARRAY_TYPE_BASE + PTime.INSTANCE.getSqlType(), PhoenixArray.class,
- null, 38);
- }
+import org.apache.phoenix.schema.SortOrder;
- @Override
- public boolean isArrayType() {
- return true;
- }
+public class PTimeArray extends PArrayDataType<Time[]> {
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PTimeArray INSTANCE = new PTimeArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PTimeArray() {
+ super("TIME ARRAY", PDataType.ARRAY_TYPE_BASE + PTime.INSTANCE.getSqlType(), PhoenixArray.class,
+ null, 38);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PTime.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PTime.INSTANCE, sortOrder, maxLength, scale,
- PTime.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PTime.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] timeArr = (Object[]) pArr.array;
- for (Object i : timeArr) {
- if (!super.isCoercibleTo(PTime.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PTime.INSTANCE, sortOrder, maxLength, scale,
+ PTime.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] timeArr = (Object[]) pArr.array;
+ for (Object i : timeArr) {
+ if (!super.isCoercibleTo(PTime.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PTime.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PTime.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestampArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestampArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestampArray.java
index d44bda9..562f139 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestampArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestampArray.java
@@ -17,93 +17,79 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.phoenix.schema.SortOrder;
+import java.sql.Timestamp;
-import java.sql.*;
+import org.apache.phoenix.schema.SortOrder;
public class PTimestampArray extends PArrayDataType<Timestamp[]> {
- public static final PTimestampArray INSTANCE = new PTimestampArray();
-
- private PTimestampArray() {
- super("TIMESTAMP ARRAY", PDataType.ARRAY_TYPE_BASE + PTimestamp.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 36);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PTimestampArray INSTANCE = new PTimestampArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PTimestampArray() {
+ super("TIMESTAMP ARRAY", PDataType.ARRAY_TYPE_BASE + PTimestamp.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 36);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PTimestamp.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PTimestamp.INSTANCE, sortOrder, maxLength, scale,
- PTimestamp.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PTimestamp.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] timeStampArr = (Object[]) pArr.array;
- for (Object i : timeStampArr) {
- if (!super.isCoercibleTo(PTimestamp.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PTimestamp.INSTANCE, sortOrder, maxLength, scale,
+ PTimestamp.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] timeStampArr = (Object[]) pArr.array;
+ for (Object i : timeStampArr) {
+ if (!super.isCoercibleTo(PTimestamp.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PTimestamp.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PTimestamp.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyintArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyintArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyintArray.java
index e0b300d..7ffaeb1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyintArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyintArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PTinyintArray extends PArrayDataType<byte[]> {
- public static final PTinyintArray INSTANCE = new PTinyintArray();
-
- private PTinyintArray() {
- super("TINYINT ARRAY", PDataType.ARRAY_TYPE_BASE + PTinyint.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 32);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PTinyintArray INSTANCE = new PTinyintArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PTinyintArray() {
+ super("TINYINT ARRAY", PDataType.ARRAY_TYPE_BASE + PTinyint.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 32);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PTinyint.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PTinyint.INSTANCE, sortOrder, maxLength, scale,
- PTinyint.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PTinyint.INSTANCE, sortOrder);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PTinyint.INSTANCE, sortOrder, maxLength, scale,
+ PTinyint.INSTANCE);
}
- PhoenixArray.PrimitiveBytePhoenixArray pArr = (PhoenixArray.PrimitiveBytePhoenixArray) value;
- byte[] byteArr = (byte[]) pArr.array;
- for (byte i : byteArr) {
- if (!super.isCoercibleTo(PTinyint.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray.PrimitiveBytePhoenixArray pArr = (PhoenixArray.PrimitiveBytePhoenixArray) value;
+ byte[] byteArr = (byte[]) pArr.array;
+ for (byte i : byteArr) {
+ if (!super.isCoercibleTo(PTinyint.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PTinyint.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PTinyint.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDateArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDateArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDateArray.java
index 859c93b..b2e173a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDateArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDateArray.java
@@ -17,94 +17,74 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.phoenix.schema.SortOrder;
-
-import java.sql.Types;
import java.util.Date;
-public class PUnsignedDateArray extends PArrayDataType<Date> {
-
- public static final PUnsignedDateArray INSTANCE = new PUnsignedDateArray();
-
- private PUnsignedDateArray() {
- super("UNSIGNED_DATE ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedDate.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 41);
- }
+import org.apache.phoenix.schema.SortOrder;
- @Override
- public boolean isArrayType() {
- return true;
- }
+public class PUnsignedDateArray extends PArrayDataType<Date> {
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedDateArray INSTANCE = new PUnsignedDateArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedDateArray() {
+ super("UNSIGNED_DATE ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedDate.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 41);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedDate.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedDate.INSTANCE, sortOrder, maxLength,
- scale, PUnsignedDate.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedDate.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] dateArr = (Object[]) pArr.array;
- for (Object i : dateArr) {
- if (!super.isCoercibleTo(PUnsignedDate.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length, PDataType actualType, SortOrder sortOrder,
+ Integer maxLength, Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedDate.INSTANCE, sortOrder, maxLength, scale,
+ PUnsignedDate.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) { return true; }
+ PhoenixArray pArr = (PhoenixArray)value;
+ Object[] dateArr = (Object[])pArr.array;
+ for (Object i : dateArr) {
+ if (!super.isCoercibleTo(PUnsignedDate.INSTANCE, i)) { return false; }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedDate.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedDate.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDoubleArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDoubleArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDoubleArray.java
index 50c69bf..be16178 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDoubleArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDoubleArray.java
@@ -17,96 +17,80 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PUnsignedDoubleArray extends PArrayDataType<double[]> {
- public static final PUnsignedDoubleArray INSTANCE = new PUnsignedDoubleArray();
-
- private PUnsignedDoubleArray() {
- super("UNSIGNED_DOUBLE ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedDouble.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 47);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedDoubleArray INSTANCE = new PUnsignedDoubleArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedDoubleArray() {
+ super("UNSIGNED_DOUBLE ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedDouble.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 47);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedDouble.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedDouble.INSTANCE, sortOrder, maxLength,
- scale, PUnsignedDouble.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedDouble.INSTANCE, sortOrder);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedDouble.INSTANCE, sortOrder, maxLength,
+ scale, PUnsignedDouble.INSTANCE);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] doubleArr = (Object[]) pArr.array;
- for (Object i : doubleArr) {
- if (!super.isCoercibleTo(PUnsignedDouble.INSTANCE, i) && (!super.isCoercibleTo(
- PUnsignedTimestamp.INSTANCE, i))
- && (!super.isCoercibleTo(PUnsignedTime.INSTANCE, i)) && (!super
- .isCoercibleTo(PUnsignedDate.INSTANCE, i))) {
- return false;
- }
+
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] doubleArr = (Object[]) pArr.array;
+ for (Object i : doubleArr) {
+ if (!super.isCoercibleTo(PUnsignedDouble.INSTANCE, i) && (!super.isCoercibleTo(
+ PUnsignedTimestamp.INSTANCE, i))
+ && (!super.isCoercibleTo(PUnsignedTime.INSTANCE, i)) && (!super
+ .isCoercibleTo(PUnsignedDate.INSTANCE, i))) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedDouble.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedDouble.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloatArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloatArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloatArray.java
index db9d075..bc1e1fb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloatArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloatArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PUnsignedFloatArray extends PArrayDataType<float[]> {
- public static final PUnsignedFloatArray INSTANCE = new PUnsignedFloatArray();
-
- private PUnsignedFloatArray() {
- super("UNSIGNED_FLOAT ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedFloat.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 46);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedFloatArray INSTANCE = new PUnsignedFloatArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedFloatArray() {
+ super("UNSIGNED_FLOAT ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedFloat.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 46);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedFloat.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedFloat.INSTANCE, sortOrder, maxLength,
- scale, PUnsignedFloat.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedFloat.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] floatArr = (Object[]) pArr.array;
- for (Object i : floatArr) {
- if (!super.isCoercibleTo(PUnsignedFloat.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedFloat.INSTANCE, sortOrder, maxLength,
+ scale, PUnsignedFloat.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] floatArr = (Object[]) pArr.array;
+ for (Object i : floatArr) {
+ if (!super.isCoercibleTo(PUnsignedFloat.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedFloat.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedFloat.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedIntArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedIntArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedIntArray.java
index 11e5f10..3d430e4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedIntArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedIntArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PUnsignedIntArray extends PArrayDataType<int[]> {
- public static final PUnsignedIntArray INSTANCE = new PUnsignedIntArray();
-
- private PUnsignedIntArray() {
- super("UNSIGNED_INT ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedInt.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 43);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedIntArray INSTANCE = new PUnsignedIntArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedIntArray() {
+ super("UNSIGNED_INT ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedInt.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 43);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedInt.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedInt.INSTANCE, sortOrder, maxLength,
- scale, PUnsignedInt.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedInt.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] intArr = (Object[]) pArr.array;
- for (Object i : intArr) {
- if (!super.isCoercibleTo(PUnsignedInt.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedInt.INSTANCE, sortOrder, maxLength,
+ scale, PUnsignedInt.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] intArr = (Object[]) pArr.array;
+ for (Object i : intArr) {
+ if (!super.isCoercibleTo(PUnsignedInt.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedInt.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedInt.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLongArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLongArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLongArray.java
index dcbe210..2a7c5ef 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLongArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLongArray.java
@@ -17,93 +17,77 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PUnsignedLongArray extends PArrayDataType<long[]> {
- public static final PUnsignedLongArray INSTANCE = new PUnsignedLongArray();
-
- private PUnsignedLongArray() {
- super("UNSIGNED_LONG ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedLong.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 42);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedLongArray INSTANCE = new PUnsignedLongArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedLongArray() {
+ super("UNSIGNED_LONG ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedLong.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 42);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedLong.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedLong.INSTANCE, sortOrder, maxLength,
- scale, PUnsignedLong.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedLong.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] longArr = (Object[]) pArr.array;
- for (Object i : longArr) {
- if (!super.isCoercibleTo(PUnsignedLong.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedLong.INSTANCE, sortOrder, maxLength,
+ scale, PUnsignedLong.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] longArr = (Object[]) pArr.array;
+ for (Object i : longArr) {
+ if (!super.isCoercibleTo(PUnsignedLong.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedLong.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedLong.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallintArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallintArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallintArray.java
index 36823c2..f481efb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallintArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallintArray.java
@@ -17,94 +17,78 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
-import java.sql.Types;
-
public class PUnsignedSmallintArray extends PArrayDataType<short[]> {
- public static final PUnsignedSmallintArray INSTANCE = new PUnsignedSmallintArray();
-
- private PUnsignedSmallintArray() {
- super("UNSIGNED_SMALLINT ARRAY",
- PDataType.ARRAY_TYPE_BASE + PUnsignedSmallint.INSTANCE.getSqlType(), PhoenixArray.class,
- null, 44);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedSmallintArray INSTANCE = new PUnsignedSmallintArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedSmallintArray() {
+ super("UNSIGNED_SMALLINT ARRAY",
+ PDataType.ARRAY_TYPE_BASE + PUnsignedSmallint.INSTANCE.getSqlType(), PhoenixArray.class,
+ null, 44);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedSmallint.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedSmallint.INSTANCE, sortOrder, maxLength,
- scale, PUnsignedSmallint.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedSmallint.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] shortArr = (Object[]) pArr.array;
- for (Object i : shortArr) {
- if (!super.isCoercibleTo(PUnsignedSmallint.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedSmallint.INSTANCE, sortOrder, maxLength,
+ scale, PUnsignedSmallint.INSTANCE);
}
- return true;
- }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] shortArr = (Object[]) pArr.array;
+ for (Object i : shortArr) {
+ if (!super.isCoercibleTo(PUnsignedSmallint.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedSmallint.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedSmallint.INSTANCE, arrayLength, maxLength);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/2620a80c/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimeArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimeArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimeArray.java
index 9d7584b..0851d48 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimeArray.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTimeArray.java
@@ -17,93 +17,79 @@
*/
package org.apache.phoenix.schema.types;
-import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
-import org.apache.phoenix.schema.SortOrder;
+import java.sql.Time;
-import java.sql.*;
+import org.apache.phoenix.schema.SortOrder;
public class PUnsignedTimeArray extends PArrayDataType<Time[]> {
- public static final PUnsignedTimeArray INSTANCE = new PUnsignedTimeArray();
-
- private PUnsignedTimeArray() {
- super("UNSIGNED_TIME ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedTime.INSTANCE.getSqlType(),
- PhoenixArray.class, null, 39);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public boolean isFixedWidth() {
- return false;
- }
+ public static final PUnsignedTimeArray INSTANCE = new PUnsignedTimeArray();
- @Override
- public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
- return compareTo(lhs, rhs);
- }
+ private PUnsignedTimeArray() {
+ super("UNSIGNED_TIME ARRAY", PDataType.ARRAY_TYPE_BASE + PUnsignedTime.INSTANCE.getSqlType(),
+ PhoenixArray.class, null, 39);
+ }
- @Override
- public Integer getByteSize() {
- return null;
- }
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
- @Override
- public byte[] toBytes(Object object) {
- return toBytes(object, SortOrder.ASC);
- }
+ @Override
+ public boolean isFixedWidth() {
+ return false;
+ }
- @Override
- public byte[] toBytes(Object object, SortOrder sortOrder) {
- return toBytes(object, PUnsignedTime.INSTANCE, sortOrder);
- }
+ @Override
+ public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+ return compareTo(lhs, rhs);
+ }
- @Override
- public Object toObject(byte[] bytes, int offset, int length,
- PDataType actualType, SortOrder sortOrder, Integer maxLength,
- Integer scale) {
- return toObject(bytes, offset, length, PUnsignedTime.INSTANCE, sortOrder, maxLength,
- scale, PUnsignedTime.INSTANCE);
- }
+ @Override
+ public Integer getByteSize() {
+ return null;
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType) {
- return isCoercibleTo(targetType, this);
- }
+ @Override
+ public byte[] toBytes(Object object) {
+ return toBytes(object, SortOrder.ASC);
+ }
- @Override
- public boolean isCoercibleTo(PDataType targetType, Object value) {
- if (value == null) {
- return true;
+ @Override
+ public byte[] toBytes(Object object, SortOrder sortOrder) {
+ return toBytes(object, PUnsignedTime.INSTANCE, sortOrder);
}
- PhoenixArray pArr = (PhoenixArray) value;
- Object[] timeArr = (Object[]) pArr.array;
- for (Object i : timeArr) {
- if (!super.isCoercibleTo(PUnsignedTime.INSTANCE, i)) {
- return false;
- }
+
+ @Override
+ public Object toObject(byte[] bytes, int offset, int length,
+ PDataType actualType, SortOrder sortOrder, Integer maxLength,
+ Integer scale) {
+ return toObject(bytes, offset, length, PUnsignedTime.INSTANCE, sortOrder, maxLength,
+ scale, PUnsignedTime.INSTANCE);
}
- return true;
- }
- @Override
- public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
- Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
- Integer desiredScale, SortOrder desiredModifier) {
- coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
- this, actualModifer, desiredModifier);
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType) {
+ return isCoercibleTo(targetType, this);
+ }
- @Override
- public int getResultSetSqlType() {
- return Types.ARRAY;
- }
+ @Override
+ public boolean isCoercibleTo(PDataType targetType, Object value) {
+ if (value == null) {
+ return true;
+ }
+ PhoenixArray pArr = (PhoenixArray) value;
+ Object[] timeArr = (Object[]) pArr.array;
+ for (Object i : timeArr) {
+ if (!super.isCoercibleTo(PUnsignedTime.INSTANCE, i)) {
+ return false;
+ }
+ }
+ return true;
+ }
- @Override
- public Object getSampleValue(Integer maxLength, Integer arrayLength) {
- return getSampleValue(PUnsignedTime.INSTANCE, arrayLength, maxLength);
- }
+ @Override
+ public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+ return getSampleValue(PUnsignedTime.INSTANCE, arrayLength, maxLength);
+ }
}
[19/50] [abbrv] phoenix git commit: PHOENIX-1954 Reserve chunks of
numbers for a sequence (Jan Fernando)
Posted by ma...@apache.org.
PHOENIX-1954 Reserve chunks of numbers for a sequence (Jan Fernando)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/3b1bfa0d
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/3b1bfa0d
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/3b1bfa0d
Branch: refs/heads/calcite
Commit: 3b1bfa0d7b83f0b9ee0ad535d6e1f99777c14cb6
Parents: 984e622
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Jul 9 20:49:03 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Jul 9 20:56:48 2015 -0700
----------------------------------------------------------------------
.../end2end/SequenceBulkAllocationIT.java | 1286 ++++++++++++++++++
phoenix-core/src/main/antlr3/PhoenixSQL.g | 5 +-
.../apache/phoenix/compile/SequenceManager.java | 70 +-
.../compile/SequenceValueExpression.java | 14 +-
.../coprocessor/SequenceRegionObserver.java | 64 +-
.../phoenix/exception/SQLExceptionCode.java | 2 +
.../apache/phoenix/jdbc/PhoenixStatement.java | 10 +-
.../apache/phoenix/parse/ParseNodeFactory.java | 6 +-
.../phoenix/parse/SequenceValueParseNode.java | 8 +-
.../phoenix/query/ConnectionQueryServices.java | 5 +-
.../query/ConnectionQueryServicesImpl.java | 23 +-
.../query/ConnectionlessQueryServicesImpl.java | 20 +-
.../query/DelegateConnectionQueryServices.java | 13 +-
.../apache/phoenix/schema/MetaDataClient.java | 2 +-
.../org/apache/phoenix/schema/Sequence.java | 107 +-
.../phoenix/schema/SequenceAllocation.java | 48 +
.../org/apache/phoenix/util/SequenceUtil.java | 47 +-
.../phoenix/schema/SequenceAllocationTest.java | 59 +
.../apache/phoenix/util/SequenceUtilTest.java | 54 +
19 files changed, 1763 insertions(+), 80 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceBulkAllocationIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceBulkAllocationIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceBulkAllocationIT.java
new file mode 100644
index 0000000..e7db1ec
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceBulkAllocationIT.java
@@ -0,0 +1,1286 @@
+/*
+ * 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.PhoenixRuntime.TENANT_ID_ATTRIB;
+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.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.apache.phoenix.util.ReadOnlyProps;
+import org.junit.After;
+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;
+
+/**
+ * Suite of integration tests that validate that Bulk Allocation of Sequence values
+ * using the NEXT <n> VALUES FOR <seq> syntax works as expected and interacts
+ * correctly with NEXT VALUE FOR <seq> and CURRENT VALUE FOR <seq>.
+ *
+ * All tests are run with both a generic connection and a multi-tenant connection.
+ *
+ */
+@RunWith(Parameterized.class)
+public class SequenceBulkAllocationIT extends BaseClientManagedTimeIT {
+
+ private static final long BATCH_SIZE = 3;
+ private static final String SELECT_NEXT_VALUE_SQL =
+ "SELECT NEXT VALUE FOR %s FROM SYSTEM.\"SEQUENCE\" LIMIT 1";
+ private static final String SELECT_CURRENT_VALUE_SQL =
+ "SELECT CURRENT VALUE FOR %s FROM SYSTEM.\"SEQUENCE\" LIMIT 1";
+ private static final String CREATE_SEQUENCE_NO_MIN_MAX_TEMPLATE =
+ "CREATE SEQUENCE bulkalloc.alpha START WITH %s INCREMENT BY %s CACHE %s";
+ private static final String CREATE_SEQUENCE_WITH_MIN_MAX_TEMPLATE =
+ "CREATE SEQUENCE bulkalloc.alpha START WITH %s INCREMENT BY %s MINVALUE %s MAXVALUE %s CACHE %s";
+ private static final String CREATE_SEQUENCE_WITH_MIN_MAX_AND_CYCLE_TEMPLATE =
+ "CREATE SEQUENCE bulkalloc.alpha START WITH %s INCREMENT BY %s MINVALUE %s MAXVALUE %s CYCLE CACHE %s";
+
+
+ private Connection conn;
+ private String tenantId;
+
+ public SequenceBulkAllocationIT(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ @BeforeClass
+ @Shadower(classBeingShadowed = BaseClientManagedTimeIT.class)
+ public static void doSetup() throws Exception {
+ Map<String, String> props = getDefaultProps();
+ // Must update config before starting server
+ props.put(QueryServices.SEQUENCE_CACHE_SIZE_ATTRIB, Long.toString(BATCH_SIZE));
+ setUpTestDriver(new ReadOnlyProps(props.entrySet().iterator()));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ // close any open connection between tests, so that connections are not leaked
+ if (conn != null) {
+ conn.close();
+ }
+ }
+
+ @Parameters
+ public static Object[] data() {
+ return new Object[] {null, "tenant1"};
+ }
+
+
+ @Test
+ public void testSequenceParseNextValuesWithNull() throws Exception {
+ nextConnection();
+ try {
+ conn.createStatement().executeQuery(
+ "SELECT NEXT NULL VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\" LIMIT 1");
+ fail("null is not allowed to be used for <n> in NEXT <n> VALUES FOR <seq>");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_MUST_BE_CONSTANT.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+ }
+
+ @Test
+ public void testSequenceParseNextValuesWithNonNumber() throws Exception {
+ nextConnection();
+ try {
+ conn.createStatement().executeQuery(
+ "SELECT NEXT '89b' VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\" LIMIT 1");
+ fail("Only integers and longs are allowed to be used for <n> in NEXT <n> VALUES FOR <seq>");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_MUST_BE_CONSTANT.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+ }
+
+
+ @Test
+ public void testSequenceParseNextValuesWithNegativeNumber() throws Exception {
+ nextConnection();
+ try {
+ conn.createStatement().executeQuery(
+ "SELECT NEXT '-1' VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\" LIMIT 1");
+ fail("null is not allowed to be used for <n> in NEXT <n> VALUES FOR <seq>");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_MUST_BE_CONSTANT.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+ }
+
+ @Test
+ public void testParseNextValuesSequenceWithZeroAllocated() throws Exception {
+ nextConnection();
+ try {
+ conn.createStatement().executeQuery(
+ "SELECT NEXT 0 VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\" LIMIT 1");
+ fail("Only integers and longs are allowed to be used for <n> in NEXT <n> VALUES FOR <seq>");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_MUST_BE_CONSTANT.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+ }
+
+
+ @Test
+ public void testNextValuesForSequenceWithNoAllocatedValues() throws Exception {
+ // Create Sequence
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(1)
+ .numAllocated(100).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ // Bulk Allocate Sequence Slots
+ final int currentValueAfterAllocation = 100;
+ reserveSlotsInBulkAndAssertValue(1, props.numAllocated);
+ assertExpectedStateInSystemSequence(props, 101);
+ assertExpectedNumberOfValuesAllocated(1, currentValueAfterAllocation, props.incrementBy, props.numAllocated);
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(currentValueAfterAllocation);
+ assertExpectedNextValueForSequence(101);
+ }
+
+ @Test
+ /**
+ * Validates we can invoke NEXT <n> VALUES FOR using bind vars.
+ */
+ public void testNextValuesForSequenceUsingBinds() throws Exception {
+
+ // Create Sequence
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(1)
+ .numAllocated(100).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ // Allocate 100 slots using SQL with Bind Params and a PreparedStatement
+ final int currentValueAfterAllocation = 100;
+ reserveSlotsInBulkUsingBindsAndAssertValue(1,props.numAllocated);
+ assertExpectedStateInSystemSequence(props, 101);
+ assertExpectedNumberOfValuesAllocated(1, currentValueAfterAllocation, props.incrementBy, props.numAllocated);
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(currentValueAfterAllocation);
+ assertExpectedNextValueForSequence(101);
+ }
+
+
+ @Test
+ public void testNextValuesForSequenceWithPreviouslyAllocatedValues() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(1);
+ assertExpectedCurrentValueForSequence(1);
+ assertExpectedNextValueForSequence(2);
+
+ // Bulk Allocate Sequence Slots
+ int currentValueAfterAllocation = 1100;
+ int nextValueAfterAllocation = currentValueAfterAllocation + props.incrementBy;
+ int startValueAfterAllocation = 101;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(currentValueAfterAllocation);
+ assertExpectedNextValueForSequence(nextValueAfterAllocation);
+ }
+
+
+ @Test
+ /**
+ * Validates that if we close a connection after performing
+ * NEXT <n> VALUES FOR <seq> the values are correctly returned from
+ * the latest batch.
+ */
+ public void testConnectionCloseReturnsSequenceValuesCorrectly() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(2).startsWith(1).cacheSize(100)
+ .numAllocated(100).build();
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(1);
+ assertExpectedCurrentValueForSequence(1);
+ assertExpectedNextValueForSequence(3);
+
+ // Bulk Allocate Sequence Slots
+ int currentValueAfterAllocation = 399;
+ int nextValueAfterAllocation = currentValueAfterAllocation + props.incrementBy;
+ int startValueAfterAllocation = 201;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+ assertExpectedCurrentValueForSequence(currentValueAfterAllocation);
+
+ // Close the Connection
+ conn.close();
+
+ // Test that sequence, doesn't have gaps after closing the connection
+ nextConnection();
+ assertExpectedNextValueForSequence(nextValueAfterAllocation);
+ assertExpectedCurrentValueForSequence(nextValueAfterAllocation);
+
+ }
+
+ @Test
+ /**
+ * Validates that calling NEXT <n> VALUES FOR <seq> works correctly with UPSERT.
+ */
+ public void testNextValuesForSequenceWithUpsert() throws Exception {
+
+ // Create Sequence
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+
+ // Create TABLE
+ nextGenericConnection();
+ conn.createStatement().execute("CREATE TABLE bulkalloc.test ( id INTEGER NOT NULL PRIMARY KEY)");
+ nextConnection();
+
+ // Grab batch from Sequence
+ assertExpectedNextValueForSequence(1);
+ assertExpectedCurrentValueForSequence(1);
+ assertExpectedNextValueForSequence(2);
+ assertExpectedStateInSystemSequence(props, 101);
+
+
+ // Perform UPSERT and validate Sequence was incremented as expected
+ conn.createStatement().execute("UPSERT INTO bulkalloc.test (id) VALUES (NEXT " + props.numAllocated + " VALUES FOR bulkalloc.alpha)");
+ conn.commit();
+ assertExpectedStateInSystemSequence(props, 1101);
+
+ // SELECT values out and verify
+ nextConnection();
+ String query = "SELECT id, NEXT VALUE FOR bulkalloc.alpha FROM bulkalloc.test";
+ ResultSet rs = conn.prepareStatement(query).executeQuery();
+ assertTrue(rs.next());
+ assertEquals(101, rs.getInt(1)); // Threw out cache of 100, incremented by 1000
+ assertEquals(1101, rs.getInt(2));
+ assertFalse(rs.next());
+ }
+
+
+
+
+ @Test
+ public void testNextValuesForSequenceWithIncrementBy() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(3).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(1);
+ assertExpectedCurrentValueForSequence(1);
+ assertExpectedNextValueForSequence(4);
+
+ // Bulk Allocate Sequence Slots
+ int currentValueAfterAllocation = 3298;
+ int startValueAfterAllocation = 301;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(3298);
+ assertExpectedNextValueForSequence(3301);
+ }
+
+ @Test
+ public void testNextValuesForSequenceWithNegativeIncrementBy() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(-1).startsWith(2000).cacheSize(100)
+ .numAllocated(1000).build();
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(2000);
+ assertExpectedCurrentValueForSequence(2000);
+ assertExpectedNextValueForSequence(1999);
+
+ // Bulk Allocate Sequence Slots
+ int currentValueAfterAllocation = 901;
+ int startValueAfterAllocation = 1900;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(901);
+ assertExpectedNextValueForSequence(900);
+ }
+
+ @Test
+ public void testNextValuesForSequenceWithNegativeIncrementByGreaterThanOne() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(-5).startsWith(2000).cacheSize(100)
+ .numAllocated(100).build();
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ // Pull first batch from Sequence
+ assertExpectedNextValueForSequence(2000);
+ assertExpectedCurrentValueForSequence(2000);
+ assertExpectedNextValueForSequence(1995);
+
+ // Bulk Allocate Sequence Slots
+ int currentValueAfterAllocation = 1005;
+ int startValueAfterAllocation = 1500;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(1005);
+ assertExpectedNextValueForSequence(1000);
+ }
+
+
+ @Test
+ /**
+ * Validates that for NEXT <n> VALUES FOR if you try an allocate more slots such that that
+ * we exceed the max value of the sequence we throw an exception. Allocating sequence values in bulk
+ * should be an all or nothing operation - if the operation succeeds clients are guaranteed that they
+ * have access to all slots requested.
+ */
+ public void testNextValuesForSequenceExceedsMaxValue() throws Exception {
+ final SequenceProperties sequenceProps =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(100).cacheSize(100)
+ .numAllocated(1000).minValue(100).maxValue(900).build();
+
+ nextConnection();
+ createSequenceWithMinMax(sequenceProps);
+ nextConnection();
+
+ // Pull first batch from the sequence
+ assertExpectedNextValueForSequence(100);
+ assertExpectedCurrentValueForSequence(100);
+ assertExpectedNextValueForSequence(101);
+
+ // Attempt to bulk Allocate more slots than available
+ try {
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + sequenceProps.numAllocated
+ + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\" LIMIT 1");
+ fail("Invoking SELECT NEXT VALUES should have thrown Reached Max Value Exception");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.SEQUENCE_VAL_REACHED_MAX_VALUE.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+
+ // Assert sequence didn't advance
+ assertExpectedCurrentValueForSequence(101);
+ assertExpectedNextValueForSequence(102);
+ }
+
+ @Test
+ /**
+ * Validates that for NEXT <n> VALUES FOR if you try an allocate more slots such that that
+ * we exceed the min value of the sequence we throw an exception. Allocating sequence values in bulk
+ * should be an all or nothing operation - if the operation succeeds clients are guaranteed that they
+ * have access to all slots requested.
+ */
+ public void testNextValuesForSequenceExceedsMinValue() throws Exception {
+ final SequenceProperties sequenceProps =
+ new SequenceProperties.Builder().incrementBy(-5).startsWith(900).cacheSize(100)
+ .numAllocated(160).minValue(100).maxValue(900).build();
+
+ nextConnection();
+ createSequenceWithMinMax(sequenceProps);
+ nextConnection();
+
+ // Pull first batch from the sequence
+ assertExpectedNextValueForSequence(900);
+ assertExpectedCurrentValueForSequence(900);
+ assertExpectedNextValueForSequence(895);
+
+ // Attempt to bulk Allocate more slots than available
+ try {
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + sequenceProps.numAllocated
+ + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\" LIMIT 1");
+ fail("Invoking SELECT NEXT VALUES should have thrown Reached Max Value Exception");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.SEQUENCE_VAL_REACHED_MIN_VALUE.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+
+ // Assert sequence didn't advance (we still throw out the cached values)
+ assertExpectedCurrentValueForSequence(895);
+ assertExpectedNextValueForSequence(890);
+ }
+
+
+ @Test
+ /**
+ * Validates that if we don't exceed the limit bulk allocation works with sequences with a
+ * min and max defined.
+ */
+ public void testNextValuesForSequenceWithMinMaxDefined() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(5).startsWith(100).cacheSize(100)
+ .numAllocated(1000).minValue(100).maxValue(6000).build();
+
+ nextConnection();
+ createSequenceWithMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(100);
+ assertExpectedCurrentValueForSequence(100);
+ assertExpectedNextValueForSequence(105);
+
+ // Bulk Allocate Sequence Slots
+ int currentValueAfterAllocation = 5595;
+ int startValueAfterAllocation = 600;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(5595);
+ assertExpectedNextValueForSequence(5600);
+ }
+
+ @Test
+ public void testNextValuesForSequenceWithDefaultMax() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(100).cacheSize(100)
+ .numAllocated(Long.MAX_VALUE - 100).build();
+
+ // Create Sequence
+ nextConnection();
+ createSequenceWithMinMax(props);
+ nextConnection();
+
+ // Bulk Allocate Sequence Slots
+ long currentValueAfterAllocation = 100;
+ long startValueAfterAllocation = Long.MAX_VALUE;
+ reserveSlotsInBulkAndAssertValue(currentValueAfterAllocation, props.numAllocated);
+ assertExpectedStateInSystemSequence(props, startValueAfterAllocation);
+
+ // Try and get next value
+ try {
+ conn.createStatement().executeQuery(String.format(SELECT_NEXT_VALUE_SQL, "bulkalloc.alpha"));
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.SEQUENCE_VAL_REACHED_MAX_VALUE.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+ }
+
+ @Test
+ /**
+ * Validates that if our current or start value is > 0 and we ask for Long.MAX
+ * and overflow to the next value, the correct Exception is thrown when
+ * the expression is evaluated.
+ */
+ public void testNextValuesForSequenceOverflowAllocation() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(100).cacheSize(100)
+ .numAllocated(Long.MAX_VALUE).build();
+
+ // Create Sequence
+ nextConnection();
+ createSequenceWithMinMax(props);
+ nextConnection();
+
+ // Bulk Allocate Sequence Slots
+ try {
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + Long.MAX_VALUE
+ + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.SEQUENCE_VAL_REACHED_MAX_VALUE.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+ }
+
+
+ @Test
+ /**
+ * Validates that specifying an bulk allocation less than the size of the cache defined on the sequence works
+ * as expected.
+ */
+ public void testNextValuesForSequenceAllocationLessThanCacheSize() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(5).startsWith(100).cacheSize(100)
+ .numAllocated(50).minValue(100).maxValue(6000).build();
+
+ nextConnection();
+ createSequenceWithMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(100);
+ assertExpectedCurrentValueForSequence(100);
+ assertExpectedNextValueForSequence(105);
+
+ // Bulk Allocate Sequence Slots
+ int currentValueAfterAllocation = 355;
+ int startValueAfterAllocation = 110;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+ assertExpectedStateInSystemSequence(props, 600);
+ assertExpectedNumberOfValuesAllocated(startValueAfterAllocation, currentValueAfterAllocation, props.incrementBy, props.numAllocated);
+
+ // Assert standard Sequence Operations return expected values
+ // 105 + (50 * 5) = 355
+ assertExpectedCurrentValueForSequence(355);
+ assertExpectedNextValueForSequence(360);
+ assertExpectedNextValueForSequence(365);
+ assertExpectedNextValueForSequence(370);
+ }
+
+ @Test
+ /**
+ * Validates that specifying an bulk allocation less than the size of the cache defined on the sequence works
+ * as expected if we don't have enough values in the cache to support the allocation.
+ */
+ public void testNextValuesForInsufficentCacheValuesAllocationLessThanCacheSize() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(5).startsWith(100).cacheSize(100)
+ .numAllocated(50).minValue(100).maxValue(6000).build();
+
+ nextConnection();
+ createSequenceWithMinMax(props);
+ nextConnection();
+
+ // Allocate 51 slots, only 49 will be left
+ int currentValueAfter51Allocations = 355; // 100 + 51 * 5
+ for (int i = 100; i <= currentValueAfter51Allocations; i = i + 5) {
+ assertExpectedNextValueForSequence(i);
+ }
+ assertExpectedCurrentValueForSequence(currentValueAfter51Allocations);
+
+ // Bulk Allocate 50 Sequence Slots which greater than amount left in cache
+ // This should throw away rest of the cache, and allocate the request slot
+ // from the next start value
+ int currentValueAfterAllocation = 845;
+ int startValueAfterAllocation = 600;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(845);
+ assertExpectedNextValueForSequence(850);
+ assertExpectedNextValueForSequence(855);
+ assertExpectedNextValueForSequence(860);
+ }
+
+ @Test
+ /**
+ * Validates that for NEXT <n> VALUES FOR is not supported on Sequences that have the
+ * CYCLE flag set to true.
+ */
+ public void testNextValuesForSequenceWithCycles() throws Exception {
+ final SequenceProperties sequenceProps =
+ new SequenceProperties.Builder().incrementBy(5).startsWith(100).cacheSize(100)
+ .numAllocated(1000).minValue(100).maxValue(900).build();
+
+ nextConnection();
+ createSequenceWithMinMaxAndCycle(sequenceProps);
+ nextConnection();
+
+ // Full first batch from the sequence
+ assertExpectedNextValueForSequence(100);
+ assertExpectedCurrentValueForSequence(100);
+ assertExpectedNextValueForSequence(105);
+
+ // Attempt to bulk Allocate more slots than available
+ try {
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + sequenceProps.numAllocated
+ + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\" LIMIT 1");
+ fail("Invoking SELECT NEXT VALUES should have failed as operation is not supported for sequences with Cycles.");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_NOT_SUPPORTED.getErrorCode(),
+ e.getErrorCode());
+ assertTrue(e.getNextException() == null);
+ }
+
+ // Assert sequence didn't advance
+ assertExpectedCurrentValueForSequence(105);
+ assertExpectedNextValueForSequence(110);
+ assertExpectedNextValueForSequence(115);
+ }
+
+ @Test
+ /**
+ * Validates that if we have multiple NEXT <n> VALUES FOR <seq> expression and the
+ * CURRENT VALUE FOR expression work correctly when used in the same statement.
+ */
+ public void testCurrentValueForAndNextValuesForExpressionsForSameSequence() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(1);
+ assertExpectedCurrentValueForSequence(1);
+ assertExpectedNextValueForSequence(2);
+
+ // Bulk Allocate Sequence Slots
+ int currentValueAfterAllocation = 1100;
+ int nextValueAfterAllocation = currentValueAfterAllocation + props.incrementBy;
+ int startValueAfterAllocation = 101;
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT CURRENT VALUE FOR bulkalloc.alpha, NEXT " + props.numAllocated + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ assertTrue(rs.next());
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+ int currentValueFor = rs.getInt(1);
+ int nextValuesFor = rs.getInt(2);
+ assertEquals("Expected the next value to be first value reserved", startValueAfterAllocation, nextValuesFor);
+ assertEquals("Expected current value to be the same as next value", startValueAfterAllocation, currentValueFor);
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(currentValueAfterAllocation);
+ assertExpectedNextValueForSequence(nextValueAfterAllocation);
+ }
+
+ @Test
+ /**
+ * Validates that if we have multiple NEXT <n> VALUES FOR <seq> expressions for the *same* sequence
+ * in a statement we only process the one which has the highest value of <n> and return the start
+ * value for that for all expressions.
+ */
+ public void testMultipleNextValuesForExpressionsForSameSequence() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(1);
+ assertExpectedCurrentValueForSequence(1);
+ assertExpectedNextValueForSequence(2);
+
+ // Bulk Allocate Sequence Slots - One for 5 and one for 1000, 1000 should have precedence
+ int currentValueAfterAllocation = 1100;
+ int nextValueAfterAllocation = currentValueAfterAllocation + props.incrementBy;
+ int startValueAfterAllocation = 101;
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT 5 VALUES FOR bulkalloc.alpha, NEXT " + props.numAllocated + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ assertTrue(rs.next());
+ int firstValue = rs.getInt(1);
+ int secondValue = rs.getInt(2);
+ assertEquals("Expected both expressions to return the same value", firstValue, secondValue);
+ assertEquals("Expected the value returned to be the highest allocation", startValueAfterAllocation, firstValue);
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(currentValueAfterAllocation);
+ assertExpectedNextValueForSequence(nextValueAfterAllocation);
+ }
+
+ @Test
+ /**
+ * Validates that if we have NEXT VALUE FOR <seq> and NEXT <n> VALUES FOR <seq> expressions for the *same* sequence
+ * in a statement we only process way and honor the value of the highest value of <n>, where for
+ * NEXT VALUE FOR <seq> is assumed to be 1.
+ */
+ public void testMultipleDifferentExpressionsForSameSequence() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ // Pull First Batch from Sequence
+ assertExpectedNextValueForSequence(1);
+
+ // Bulk Allocate Sequence Slots and Get Next Value in Same Statement
+ int currentValueAfterAllocation = 1100;
+ int nextValueAfterAllocation = currentValueAfterAllocation + props.incrementBy;
+ int startValueAfterAllocation = 101;
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT VALUE FOR bulkalloc.alpha, "
+ + "NEXT " + props.numAllocated + " VALUES FOR bulkalloc.alpha, "
+ + "CURRENT VALUE FOR bulkalloc.alpha, "
+ + "NEXT 999 VALUES FOR bulkalloc.alpha "
+ + "FROM SYSTEM.\"SEQUENCE\"");
+ assertTrue(rs.next());
+ assertBulkAllocationSucceeded(props, currentValueAfterAllocation, startValueAfterAllocation);
+
+ // Assert all values returned are the same
+ // Expect them to be the highest value from NEXT VALUE or NEXT <n> VALUES FOR
+ int previousVal = 0;
+ for (int i = 1; i <= 4; i++) {
+ int currentVal = rs.getInt(i);
+ if (i != 1) {
+ assertEquals(
+ "Expected all NEXT VALUE FOR and NEXT <n> VALUES FOR expressions to return the same value",
+ previousVal, currentVal);
+ }
+ previousVal = currentVal;
+ }
+
+ // Assert standard Sequence Operations return expected values
+ assertExpectedCurrentValueForSequence(currentValueAfterAllocation);
+ assertExpectedNextValueForSequence(nextValueAfterAllocation);
+ }
+
+
+ @Test
+ /**
+ * Validates that using NEXT <n> VALUES FOR on different sequences in the
+ * same statement with *different* values of <n> works as expected. This
+ * test validates that we keep our numAllocated array and sequence keys in
+ * sync during the sequence management process.
+ */
+ public void testMultipleNextValuesForExpressionsForDifferentSequences() throws Exception {
+
+ nextConnection();
+ conn.createStatement().execute("CREATE SEQUENCE bulkalloc.alpha START WITH 30 INCREMENT BY 3 CACHE 100");
+ conn.createStatement().execute("CREATE SEQUENCE bulkalloc.beta START WITH 100 INCREMENT BY 5 CACHE 50");
+ nextConnection();
+
+ // Bulk Allocate Sequence Slots for Two Sequences
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT 100 VALUES FOR bulkalloc.alpha, NEXT 1000 VALUES FOR bulkalloc.beta FROM SYSTEM.\"SEQUENCE\"");
+ assertTrue(rs.next());
+ assertEquals(30, rs.getInt(1));
+ assertEquals(100, rs.getInt(2));
+
+ // Assert standard Sequence Operations return expected values
+ for (int i = 330; i < 330 + (2 * 100); i += 3) {
+ assertExpectedCurrentValueForSequence(i - 3, "bulkalloc.alpha");
+ assertExpectedNextValueForSequence(i, "bulkalloc.alpha");
+ }
+
+ for (int i = 5100; i < 5100 + (2 * 1000); i += 5) {
+ assertExpectedCurrentValueForSequence(i - 5, "bulkalloc.beta");
+ assertExpectedNextValueForSequence(i, "bulkalloc.beta");
+ }
+ }
+
+ @Test
+ /**
+ * Validates that calling NEXT <n> VALUES FOR with EXPLAIN PLAN doesn't use
+ * allocate any slots.
+ */
+ public void testExplainPlanValidatesSequences() throws Exception {
+
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(3).startsWith(30).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+
+ nextGenericConnection();
+ conn.createStatement().execute("CREATE TABLE bulkalloc.simpletbl (k BIGINT NOT NULL PRIMARY KEY)");
+ nextConnection();
+
+ // Bulk Allocate Sequence Slots
+ int startValueAfterAllocation = 30;
+ reserveSlotsInBulkAndAssertValue(startValueAfterAllocation, props.numAllocated);
+
+ // Execute EXPLAIN PLAN multiple times, which should not change Sequence values
+ for (int i = 0; i < 3; i++) {
+ conn.createStatement().executeQuery("EXPLAIN SELECT NEXT 1000 VALUES FOR bulkalloc.alpha FROM bulkalloc.simpletbl");
+ }
+
+ // Validate the current value was not advanced and was the starting value
+ assertExpectedStateInSystemSequence(props, 3030);
+
+ // Assert standard Sequence Operations return expected values
+ int startValue = 3030;
+ for (int i = startValue; i < startValue + (2 * props.cacheSize); i += props.incrementBy) {
+ assertExpectedCurrentValueForSequence(i - props.incrementBy);
+ assertExpectedNextValueForSequence(i);
+ }
+ }
+
+ @Test
+ public void testExplainPlanForNextValuesFor() throws Exception {
+
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(3).startsWith(30).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextGenericConnection();
+ conn.createStatement().execute("CREATE TABLE bulkalloc.simpletbl (k BIGINT NOT NULL PRIMARY KEY)");
+ nextConnection();
+
+ // Execute EXPLAIN PLAN which should not change Sequence values
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN SELECT NEXT 1000 VALUES FOR bulkalloc.alpha FROM bulkalloc.simpletbl");
+
+ // Assert output for Explain Plain result is as expected
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER BULKALLOC.SIMPLETBL\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT RESERVE VALUES FROM 1 SEQUENCE", QueryUtil.getExplainPlan(rs));
+ }
+
+
+ /**
+ * Performs a multithreaded test whereby we interleave reads from the result set of
+ * NEXT VALUE FOR and NEXT <n> VALUES FOR to make sure we get expected values with the
+ * following order of execution:
+ *
+ * 1) Execute expression NEXT <n> VALUES FOR <seq>
+ * 2) Execute expression NEXT VALUE FOR <seq>
+ * 3) Read back value from expression NEXT VALUE FOR <seq> via rs.next()
+ * 4) Read back value from expression NEXT <n> VALUES FOR <seq> via rs.next()
+ */
+ public void testNextValuesForMixedWithNextValueForMultiThreaded() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(1);
+ assertExpectedCurrentValueForSequence(1);
+ assertExpectedNextValueForSequence(2);
+
+ // Bulk Allocate Sequence Slots
+ final long startValueAfterAllocation1 = 101;
+ final long startValueAfterAllocation2 = 1101;
+ final long numSlotToAllocate = props.numAllocated;
+
+ // Setup and run tasks in independent Threads
+ ExecutorService executorService = Executors.newCachedThreadPool();
+ try {
+ final CountDownLatch latch1 = new CountDownLatch(1);
+ final CountDownLatch latch2 = new CountDownLatch(1);
+
+ Callable<Long> task1 = new Callable<Long>() {
+
+ @Override
+ public Long call() throws Exception {
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + numSlotToAllocate + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ latch1.countDown(); // Allows NEXT VALUE FOR thread to proceed
+ latch2.await(); // Waits until NEXT VALUE FOR thread reads and increments currentValue
+ rs.next();
+ return rs.getLong(1);
+ }
+
+ };
+
+ Callable<Long> task2 = new Callable<Long>() {
+
+ @Override
+ public Long call() throws Exception {
+ latch1.await(); // Wait for execution of NEXT <n> VALUES FOR expression
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT VALUE FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ rs.next();
+ long retVal = rs.getLong(1);
+ latch2.countDown(); // Allow NEXT <n> VALUES for thread to completed
+ return retVal;
+ }
+
+ };
+
+ @SuppressWarnings("unchecked")
+ List<Future<Long>> futures = executorService.invokeAll(Lists.newArrayList(task1, task2), 20, TimeUnit.SECONDS);
+ assertEquals(startValueAfterAllocation1, futures.get(0).get(10, TimeUnit.SECONDS).longValue());
+ assertEquals(startValueAfterAllocation2, futures.get(1).get(10, TimeUnit.SECONDS).longValue());
+ } finally {
+ executorService.shutdown();
+ }
+ }
+
+ @Test
+ public void testMultipleNextValuesWithDiffAllocsForMultiThreaded() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ assertExpectedNextValueForSequence(1);
+ assertExpectedCurrentValueForSequence(1);
+ assertExpectedNextValueForSequence(2);
+
+ // Bulk Allocate Sequence Slots
+ final long startValueAfterAllocation1 = 101;
+ final long startValueAfterAllocation2 = 1101;
+ final long numSlotToAllocate1 = 1000;
+ final long numSlotToAllocate2 = 100;
+
+ // Setup and run tasks in independent Threads
+ ExecutorService executorService = Executors.newCachedThreadPool();
+ try {
+ final CountDownLatch latch1 = new CountDownLatch(1);
+ final CountDownLatch latch2 = new CountDownLatch(1);
+
+ Callable<Long> task1 = new Callable<Long>() {
+
+ @Override
+ public Long call() throws Exception {
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + numSlotToAllocate1 + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ rs.next();
+ latch1.countDown(); // Allows other thread to proceed
+ latch2.await();
+ return rs.getLong(1);
+ }
+
+ };
+
+ Callable<Long> task2 = new Callable<Long>() {
+
+ @Override
+ public Long call() throws Exception {
+ latch1.await(); // Wait for other thread to execut of NEXT <n> VALUES FOR expression
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + numSlotToAllocate2 + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ rs.next();
+ long retVal = rs.getLong(1);
+ latch2.countDown(); // Allow thread to completed
+ return retVal;
+ }
+
+ };
+
+ @SuppressWarnings("unchecked")
+ List<Future<Long>> futures = executorService.invokeAll(Lists.newArrayList(task1, task2), 5, TimeUnit.SECONDS);
+
+ // Retrieve value from Thread running NEXT <n> VALUES FOR
+ Long retValue1 = futures.get(0).get(5, TimeUnit.SECONDS);
+ assertEquals(startValueAfterAllocation1, retValue1.longValue());
+
+ // Retrieve value from Thread running NEXT VALUE FOR
+ Long retValue2 = futures.get(1).get(5, TimeUnit.SECONDS);
+ assertEquals(startValueAfterAllocation2, retValue2.longValue());
+
+ } finally {
+ executorService.shutdown();
+ }
+ }
+
+ @Test
+ public void testMultipleNextValuesWithSameAllocsForMultiThreaded() throws Exception {
+ final SequenceProperties props =
+ new SequenceProperties.Builder().incrementBy(1).startsWith(1).cacheSize(100)
+ .numAllocated(1000).build();
+
+ nextConnection();
+ createSequenceWithNoMinMax(props);
+ nextConnection();
+
+ // Bulk Allocate Sequence Slots
+ final long startValueAfterAllocation1 = 1;
+ final long startValueAfterAllocation2 = 1001;
+ final long numSlotToAllocate1 = 1000;
+ final long numSlotToAllocate2 = 1000;
+
+ // Setup and run tasks in independent Threads
+ ExecutorService executorService = Executors.newCachedThreadPool();
+ try {
+ final CountDownLatch latch1 = new CountDownLatch(1);
+ final CountDownLatch latch2 = new CountDownLatch(1);
+
+ Callable<Long> task1 = new Callable<Long>() {
+
+ @Override
+ public Long call() throws Exception {
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + numSlotToAllocate1 + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ latch1.countDown(); // Allows other thread to proceed
+ latch2.await();
+ rs.next();
+ return rs.getLong(1);
+ }
+
+ };
+
+ Callable<Long> task2 = new Callable<Long>() {
+
+ @Override
+ public Long call() throws Exception {
+ latch1.await(); // Wait for other thread to execut of NEXT <n> VALUES FOR expression
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + numSlotToAllocate2 + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ rs.next();
+ long retVal = rs.getLong(1);
+ latch2.countDown(); // Allow thread to completed
+ return retVal;
+ }
+
+ };
+
+ // Because of the way the threads are interleaved the ranges used by each thread will the reserve
+ // of the order to statement execution
+ @SuppressWarnings("unchecked")
+ List<Future<Long>> futures = executorService.invokeAll(Lists.newArrayList(task1, task2), 5, TimeUnit.SECONDS);
+ assertEquals(startValueAfterAllocation2, futures.get(0).get(5, TimeUnit.SECONDS).longValue());
+ assertEquals(startValueAfterAllocation1, futures.get(1).get(5, TimeUnit.SECONDS).longValue());
+
+ } finally {
+ executorService.shutdown();
+ }
+ }
+
+ // -----------------------------------------------------------------
+ // Private Helper Methods
+ // -----------------------------------------------------------------
+ private void assertBulkAllocationSucceeded(SequenceProperties props,
+ int currentValueAfterAllocation, int startValueAfterAllocation) throws SQLException {
+ int nextValueAfterAllocation = currentValueAfterAllocation + props.incrementBy;
+ assertExpectedStateInSystemSequence(props, nextValueAfterAllocation);
+ assertExpectedNumberOfValuesAllocated(startValueAfterAllocation, currentValueAfterAllocation, props.incrementBy, props.numAllocated);
+ }
+
+
+ private void createSequenceWithNoMinMax(final SequenceProperties props) throws SQLException {
+ conn.createStatement().execute(
+ String.format(CREATE_SEQUENCE_NO_MIN_MAX_TEMPLATE, props.startsWith,
+ props.incrementBy, props.cacheSize));
+ }
+
+ private void createSequenceWithMinMax(final SequenceProperties props) throws SQLException {
+ conn.createStatement().execute(
+ String.format(CREATE_SEQUENCE_WITH_MIN_MAX_TEMPLATE, props.startsWith,
+ props.incrementBy, props.minValue, props.maxValue, props.cacheSize));
+ }
+
+ private void createSequenceWithMinMaxAndCycle(final SequenceProperties props) throws SQLException {
+ conn.createStatement().execute(
+ String.format(CREATE_SEQUENCE_WITH_MIN_MAX_AND_CYCLE_TEMPLATE, props.startsWith,
+ props.incrementBy, props.minValue, props.maxValue, props.cacheSize));
+ }
+
+ private void reserveSlotsInBulkAndAssertValue(long expectedValue, long numSlotToAllocate)
+ throws SQLException {
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT NEXT " + numSlotToAllocate + " VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ assertTrue(rs.next());
+ assertEquals(expectedValue, rs.getInt(1));
+ }
+
+ private void reserveSlotsInBulkUsingBindsAndAssertValue(int expectedValue, long numSlotToAllocate)
+ throws SQLException {
+ PreparedStatement ps = conn.prepareStatement("SELECT NEXT ? VALUES FOR bulkalloc.alpha FROM SYSTEM.\"SEQUENCE\"");
+ ps.setLong(1, numSlotToAllocate);
+ ResultSet rs = ps.executeQuery();
+ assertTrue(rs.next());
+ int retValue = rs.getInt(1);
+ assertEquals(expectedValue, retValue);
+ }
+
+ private void assertExpectedCurrentValueForSequence(int expectedValue) throws SQLException {
+ assertExpectedCurrentValueForSequence(expectedValue, "bulkalloc.alpha");
+ }
+
+ private void assertExpectedCurrentValueForSequence(int expectedValue, String sequenceName) throws SQLException {
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery(String.format(SELECT_CURRENT_VALUE_SQL, sequenceName));
+ assertTrue(rs.next());
+ assertEquals(expectedValue, rs.getInt(1));
+ }
+
+ private void assertExpectedNextValueForSequence(int expectedValue) throws SQLException {
+ assertExpectedNextValueForSequence(expectedValue, "bulkalloc.alpha");
+ }
+
+ private void assertExpectedNextValueForSequence(int expectedValue, String sequenceName) throws SQLException {
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery(String.format(SELECT_NEXT_VALUE_SQL, sequenceName));
+ assertTrue(rs.next());
+ assertEquals(expectedValue, rs.getInt(1));
+ }
+
+
+ /**
+ * Returns a non-tenant specific connection.
+ */
+ private void nextGenericConnection() throws Exception {
+ if (conn != null) conn.close();
+ long ts = nextTimestamp();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
+ conn = DriverManager.getConnection(getUrl(), props);
+ }
+
+ private void nextConnection() throws Exception {
+ if (conn != null) conn.close();
+ long ts = nextTimestamp();
+ if (tenantId != null) {
+ // Create tenant specific connection
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(nextTimestamp()));
+ this.conn = DriverManager.getConnection(getUrl() + ';' + TENANT_ID_ATTRIB + '=' + "tenant1", props);
+
+ } else {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
+ conn = DriverManager.getConnection(getUrl(), props);
+ }
+ }
+
+ private void assertExpectedStateInSystemSequence(SequenceProperties props, long currentValue)
+ throws SQLException {
+ // Validate state in System.Sequence
+ ResultSet rs =
+ conn.createStatement()
+ .executeQuery(
+ "SELECT start_with, current_value, increment_by, cache_size, min_value, max_value, cycle_flag, sequence_schema, sequence_name FROM SYSTEM.\"SEQUENCE\"");
+ assertTrue(rs.next());
+ assertEquals(props.startsWith, rs.getLong("start_with"));
+ assertEquals(props.incrementBy, rs.getLong("increment_by"));
+ assertEquals(props.cacheSize, rs.getLong("cache_size"));
+ assertEquals(false, rs.getBoolean("cycle_flag"));
+ assertEquals("BULKALLOC", rs.getString("sequence_schema"));
+ assertEquals("ALPHA", rs.getString("sequence_name"));
+ assertEquals(currentValue, rs.getLong("current_value"));
+ assertEquals(props.minValue, rs.getLong("min_value"));
+ assertEquals(props.maxValue, rs.getLong("max_value"));
+ assertFalse(rs.next());
+ }
+
+ private void assertExpectedNumberOfValuesAllocated(long firstValue, long lastValue,
+ int incrementBy, long numAllocated) {
+ int cnt = 0;
+ for (long i = firstValue; (incrementBy > 0 ? i <= lastValue : i >= lastValue); i += incrementBy) {
+ cnt++;
+ }
+ assertEquals("Incorrect number of values allocated: " + cnt, numAllocated, cnt);
+ }
+
+ private static class SequenceProperties {
+
+ private final long numAllocated;
+ private final int incrementBy;
+ private final int startsWith;
+ private final int cacheSize;
+ private final long minValue;
+ private final long maxValue;
+
+ public SequenceProperties(Builder builder) {
+ this.numAllocated = builder.numAllocated;
+ this.incrementBy = builder.incrementBy;
+ this.startsWith = builder.startsWith;
+ this.cacheSize = builder.cacheSize;
+ this.minValue = builder.minValue;
+ this.maxValue = builder.maxValue;
+ }
+
+ private static class Builder {
+
+ long maxValue = Long.MAX_VALUE;
+ long minValue = Long.MIN_VALUE;
+ long numAllocated = 100;
+ int incrementBy = 1;
+ int startsWith = 1;
+ int cacheSize = 100;
+
+ public Builder numAllocated(long numAllocated) {
+ this.numAllocated = numAllocated;
+ return this;
+ }
+
+ public Builder startsWith(int startsWith) {
+ this.startsWith = startsWith;
+ return this;
+ }
+
+ public Builder cacheSize(int cacheSize) {
+ this.cacheSize = cacheSize;
+ return this;
+ }
+
+ public Builder incrementBy(int incrementBy) {
+ this.incrementBy = incrementBy;
+ return this;
+ }
+
+ public Builder minValue(long minValue) {
+ this.minValue = minValue;
+ return this;
+ }
+
+ public Builder maxValue(long maxValue) {
+ this.maxValue = maxValue;
+ return this;
+ }
+
+ public SequenceProperties build() {
+ return new SequenceProperties(this);
+ }
+
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/antlr3/PhoenixSQL.g
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g
index ca5e778..10fda68 100644
--- a/phoenix-core/src/main/antlr3/PhoenixSQL.g
+++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g
@@ -903,7 +903,10 @@ term returns [ParseNode ret]
}
| (n=NEXT | CURRENT) VALUE FOR s=from_table_name
{ contextStack.peek().hasSequences(true);
- $ret = n==null ? factory.currentValueFor(s) : factory.nextValueFor(s); }
+ $ret = n==null ? factory.currentValueFor(s) : factory.nextValueFor(s, null); }
+ | (n=NEXT) lorb=literal_or_bind VALUES FOR s=from_table_name
+ { contextStack.peek().hasSequences(true);
+ $ret = factory.nextValueFor(s, lorb); }
;
one_or_more_expressions returns [List<ParseNode> ret]
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceManager.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceManager.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceManager.java
index ede6d9c..5ec8cd2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceManager.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceManager.java
@@ -24,16 +24,23 @@ import java.util.List;
import java.util.Map;
import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.ParseNode;
import org.apache.phoenix.parse.SequenceValueParseNode;
import org.apache.phoenix.parse.SequenceValueParseNode.Op;
import org.apache.phoenix.parse.TableName;
import org.apache.phoenix.query.ConnectionQueryServices;
import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.Sequence;
+import org.apache.phoenix.schema.SequenceAllocation;
import org.apache.phoenix.schema.SequenceKey;
import org.apache.phoenix.schema.tuple.DelegateTuple;
import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PLong;
+import org.apache.phoenix.util.SequenceUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -41,7 +48,7 @@ import com.google.common.collect.Maps;
public class SequenceManager {
private final PhoenixStatement statement;
private int[] sequencePosition;
- private List<SequenceKey> nextSequences;
+ private List<SequenceAllocation> nextSequences;
private List<SequenceKey> currentSequences;
private final Map<SequenceKey,SequenceValueExpression> sequenceMap = Maps.newHashMap();
private final BitSet isNextSequence = new BitSet();
@@ -113,20 +120,30 @@ public class SequenceManager {
}
}
- public SequenceValueExpression newSequenceReference(SequenceValueParseNode node) {
+ public SequenceValueExpression newSequenceReference(SequenceValueParseNode node) throws SQLException {
PName tenantName = statement.getConnection().getTenantId();
String tenantId = tenantName == null ? null : tenantName.getString();
TableName tableName = node.getTableName();
int nSaltBuckets = statement.getConnection().getQueryServices().getSequenceSaltBuckets();
+ ParseNode numToAllocateNode = node.getNumToAllocateNode();
+
+ long numToAllocate = determineNumToAllocate(tableName, numToAllocateNode);
SequenceKey key = new SequenceKey(tenantId, tableName.getSchemaName(), tableName.getTableName(), nSaltBuckets);
SequenceValueExpression expression = sequenceMap.get(key);
if (expression == null) {
int index = sequenceMap.size();
- expression = new SequenceValueExpression(key, node.getOp(), index);
+ expression = new SequenceValueExpression(key, node.getOp(), index, numToAllocate);
sequenceMap.put(key, expression);
- } else if (expression.op != node.getOp()){
- expression = new SequenceValueExpression(key, node.getOp(), expression.getIndex());
- }
+ } else if (expression.op != node.getOp() || expression.getNumToAllocate() < numToAllocate) {
+ // Keep the maximum allocation size we see in a statement
+ SequenceValueExpression oldExpression = expression;
+ expression = new SequenceValueExpression(key, node.getOp(), expression.getIndex(), Math.max(expression.getNumToAllocate(), numToAllocate));
+ if (oldExpression.getNumToAllocate() < numToAllocate) {
+ // If we found a NEXT VALUE expression with a higher number to allocate
+ // We override the original expression
+ sequenceMap.put(key, expression);
+ }
+ }
// If we see a NEXT and a CURRENT, treat the CURRENT just like a NEXT
if (node.getOp() == Op.NEXT_VALUE) {
isNextSequence.set(expression.getIndex());
@@ -134,6 +151,38 @@ public class SequenceManager {
return expression;
}
+
+ /**
+ * If caller specified used NEXT <n> VALUES FOR <seq> expression then we have set the numToAllocate.
+ * If numToAllocate is > 1 we treat this as a bulk reservation of a block of sequence slots.
+ *
+ * @throws a SQLException if we can't compile the expression
+ */
+ private long determineNumToAllocate(TableName sequenceName, ParseNode numToAllocateNode)
+ throws SQLException {
+
+ if (numToAllocateNode != null) {
+ final StatementContext context = new StatementContext(statement);
+ ExpressionCompiler expressionCompiler = new ExpressionCompiler(context);
+ Expression expression = numToAllocateNode.accept(expressionCompiler);
+ ImmutableBytesWritable ptr = context.getTempPtr();
+ expression.evaluate(null, ptr);
+ if (ptr.getLength() == 0 || !expression.getDataType().isCoercibleTo(PLong.INSTANCE)) {
+ throw SequenceUtil.getException(sequenceName.getSchemaName(), sequenceName.getTableName(), SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_MUST_BE_CONSTANT);
+ }
+
+ // Parse <n> and make sure it is greater than 0. We don't support allocating 0 or negative values!
+ long numToAllocate = (long) PLong.INSTANCE.toObject(ptr, expression.getDataType());
+ if (numToAllocate < 1) {
+ throw SequenceUtil.getException(sequenceName.getSchemaName(), sequenceName.getTableName(), SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_MUST_BE_CONSTANT);
+ }
+ return numToAllocate;
+
+ } else {
+ // Standard Sequence Allocation Behavior
+ return SequenceUtil.DEFAULT_NUM_SLOTS_TO_ALLOCATE;
+ }
+ }
public void validateSequences(Sequence.ValueOp action) throws SQLException {
if (sequenceMap.isEmpty()) {
@@ -146,14 +195,17 @@ public class SequenceManager {
currentSequences = Lists.newArrayListWithExpectedSize(maxSize);
for (Map.Entry<SequenceKey, SequenceValueExpression> entry : sequenceMap.entrySet()) {
if (isNextSequence.get(entry.getValue().getIndex())) {
- nextSequences.add(entry.getKey());
+ nextSequences.add(new SequenceAllocation(entry.getKey(), entry.getValue().getNumToAllocate()));
} else {
currentSequences.add(entry.getKey());
}
}
long[] srcSequenceValues = new long[nextSequences.size()];
SQLException[] sqlExceptions = new SQLException[nextSequences.size()];
+
+ // Sort the next sequences to prevent deadlocks
Collections.sort(nextSequences);
+
// Create reverse indexes
for (int i = 0; i < nextSequences.size(); i++) {
sequencePosition[i] = sequenceMap.get(nextSequences.get(i)).getIndex();
@@ -168,4 +220,6 @@ public class SequenceManager {
services.validateSequences(nextSequences, timestamp, srcSequenceValues, sqlExceptions, action);
setSequenceValues(srcSequenceValues, dstSequenceValues, sqlExceptions);
}
-}
+
+}
+
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceValueExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceValueExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceValueExpression.java
index cdaae68..71e2d02 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceValueExpression.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/SequenceValueExpression.java
@@ -32,13 +32,23 @@ public class SequenceValueExpression extends BaseTerminalExpression {
private final SequenceKey key;
final Op op;
private final int index;
+ private final long numToAllocate;
- public SequenceValueExpression(SequenceKey key, Op op, int index) {
+ public SequenceValueExpression(SequenceKey key, Op op, int index, long numToAllocate) {
this.key = key;
this.op = op;
this.index = index;
+ this.numToAllocate = numToAllocate;
}
+ public long getNumToAllocate() {
+ return numToAllocate;
+ }
+
+ public SequenceKey getKey() {
+ return key;
+ }
+
public int getIndex() {
return index;
}
@@ -73,7 +83,7 @@ public class SequenceValueExpression extends BaseTerminalExpression {
@Override
public String toString() {
- return op.getName() + " VALUE FOR " + SchemaUtil.getTableName(key.getSchemaName(),key.getSequenceName());
+ return op.getName() + (numToAllocate == 1 ? " VALUE " : (" " + numToAllocate + " VALUES " )) + "FOR " + SchemaUtil.getTableName(key.getSchemaName(),key.getSequenceName());
}
@Override
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/SequenceRegionObserver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/SequenceRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/SequenceRegionObserver.java
index 9b5f040..bb6c4b5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/SequenceRegionObserver.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/SequenceRegionObserver.java
@@ -41,17 +41,17 @@ import org.apache.hadoop.hbase.io.TimeRange;
import org.apache.hadoop.hbase.regionserver.Region;
import org.apache.hadoop.hbase.regionserver.Region.RowLock;
import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.phoenix.util.EnvironmentEdgeManager;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.Sequence;
+import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.types.PBoolean;
-import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PLong;
-import org.apache.phoenix.schema.Sequence;
-import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.EnvironmentEdgeManager;
import org.apache.phoenix.util.KeyValueUtil;
import org.apache.phoenix.util.MetaDataUtil;
import org.apache.phoenix.util.SequenceUtil;
@@ -77,6 +77,7 @@ public class SequenceRegionObserver extends BaseRegionObserver {
public static final String OPERATION_ATTRIB = "SEQUENCE_OPERATION";
public static final String MAX_TIMERANGE_ATTRIB = "MAX_TIMERANGE";
public static final String CURRENT_VALUE_ATTRIB = "CURRENT_VALUE";
+ public static final String NUM_TO_ALLOCATE = "NUM_TO_ALLOCATE";
private static final byte[] SUCCESS_VALUE = PInteger.INSTANCE.toBytes(Integer.valueOf(Sequence.SUCCESS));
private static Result getErrorResult(byte[] row, long timestamp, int errorCode) {
@@ -138,10 +139,8 @@ public class SequenceRegionObserver extends BaseRegionObserver {
if (result.isEmpty()) {
return getErrorResult(row, maxTimestamp, SQLExceptionCode.SEQUENCE_UNDEFINED.getErrorCode());
}
- if (validateOnly) {
- return result;
- }
+
KeyValue currentValueKV = Sequence.getCurrentValueKV(result);
KeyValue incrementByKV = Sequence.getIncrementByKV(result);
KeyValue cacheSizeKV = Sequence.getCacheSizeKV(result);
@@ -224,6 +223,28 @@ public class SequenceRegionObserver extends BaseRegionObserver {
cycleKV.getValueOffset(), cycleKV.getValueLength());
}
+ long numSlotsToAllocate = calculateNumSlotsToAllocate(increment);
+
+ // We don't support Bulk Allocations on sequences that have the CYCLE flag set to true
+ if (cycle && !SequenceUtil.isCycleAllowed(numSlotsToAllocate)) {
+ return getErrorResult(row, maxTimestamp, SQLExceptionCode.NUM_SEQ_TO_ALLOCATE_NOT_SUPPORTED.getErrorCode());
+ }
+
+ // Bulk Allocations are expressed by NEXT <n> VALUES FOR
+ if (SequenceUtil.isBulkAllocation(numSlotsToAllocate)) {
+ if (SequenceUtil.checkIfLimitReached(currentValue, minValue, maxValue, incrementBy, cacheSize, numSlotsToAllocate)) {
+ // If we try to allocate more slots than the limit we return an error.
+ // Allocating sequence values in bulk should be an all or nothing operation.
+ // If the operation succeeds clients are guaranteed that they have reserved
+ // all the slots requested.
+ return getErrorResult(row, maxTimestamp, SequenceUtil.getLimitReachedErrorCode(increasingSeq).getErrorCode());
+ }
+ }
+
+ if (validateOnly) {
+ return result;
+ }
+
// return if we have run out of sequence values
if (limitReached) {
if (cycle) {
@@ -231,16 +252,15 @@ public class SequenceRegionObserver extends BaseRegionObserver {
currentValue = increasingSeq ? minValue : maxValue;
}
else {
- SQLExceptionCode code = increasingSeq ? SQLExceptionCode.SEQUENCE_VAL_REACHED_MAX_VALUE
- : SQLExceptionCode.SEQUENCE_VAL_REACHED_MIN_VALUE;
- return getErrorResult(row, maxTimestamp, code.getErrorCode());
+ return getErrorResult(row, maxTimestamp, SequenceUtil.getLimitReachedErrorCode(increasingSeq).getErrorCode());
}
}
-
+
// check if the limit was reached
- limitReached = SequenceUtil.checkIfLimitReached(currentValue, minValue, maxValue, incrementBy, cacheSize);
- // update currentValue
- currentValue += incrementBy * cacheSize;
+ limitReached = SequenceUtil.checkIfLimitReached(currentValue, minValue, maxValue, incrementBy, cacheSize, numSlotsToAllocate);
+
+ // update currentValue
+ currentValue += incrementBy * (SequenceUtil.isBulkAllocation(numSlotsToAllocate) ? numSlotsToAllocate : cacheSize);
// update the currentValue of the Result row
KeyValue newCurrentValueKV = createKeyValue(row, PhoenixDatabaseMetaData.CURRENT_VALUE_BYTES, currentValue, timestamp);
Sequence.replaceCurrentValueKV(cells, newCurrentValueKV);
@@ -264,6 +284,7 @@ public class SequenceRegionObserver extends BaseRegionObserver {
region.closeRegionOperation();
}
}
+
/**
* Creates a new KeyValue for a long value
@@ -417,5 +438,20 @@ public class SequenceRegionObserver extends BaseRegionObserver {
region.closeRegionOperation();
}
}
+
+ /**
+ * Determines whether a request for incrementing the sequence was a bulk allocation and if so
+ * what the number of slots to allocate is. This is triggered by the NEXT <n> VALUES FOR expression.
+ * For backwards compatibility with older clients, we default the value to 1 which preserves
+ * existing behavior when invoking NEXT VALUE FOR.
+ */
+ private long calculateNumSlotsToAllocate(final Increment increment) {
+ long numToAllocate = 1;
+ byte[] numToAllocateBytes = increment.getAttribute(SequenceRegionObserver.NUM_TO_ALLOCATE);
+ if (numToAllocateBytes != null) {
+ numToAllocate = Bytes.toLong(numToAllocateBytes);
+ }
+ return numToAllocate;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/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 cc8b02a..b9f81fb 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
@@ -276,6 +276,8 @@ public enum SQLExceptionCode {
SEQUENCE_VAL_REACHED_MAX_VALUE(1212, "42Z12", "Reached MAXVALUE of sequence"),
SEQUENCE_VAL_REACHED_MIN_VALUE(1213, "42Z13", "Reached MINVALUE of sequence"),
INCREMENT_BY_MUST_NOT_BE_ZERO(1214, "42Z14", "Sequence INCREMENT BY value cannot be zero"),
+ NUM_SEQ_TO_ALLOCATE_MUST_BE_CONSTANT(1215, "42Z15", "Sequence NEXT n VALUES FOR must be a postive integer or constant." ),
+ NUM_SEQ_TO_ALLOCATE_NOT_SUPPORTED(1216, "42Z16", "Sequence NEXT n VALUES FOR is not supported for Sequences with the CYCLE flag" ),
/** Parser error. (errorcode 06, sqlState 42P) */
PARSER_ERROR(601, "42P00", "Syntax error.", Factory.SYTAX_ERROR),
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
index f323ec4..9689589 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
@@ -232,7 +232,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
}
protected QueryPlan optimizeQuery(CompilableStatement stmt) throws SQLException {
- QueryPlan plan = stmt.compilePlan(this, Sequence.ValueOp.RESERVE_SEQUENCE);
+ QueryPlan plan = stmt.compilePlan(this, Sequence.ValueOp.VALIDATE_SEQUENCE);
return connection.getQueryServices().getOptimizer().optimize(this, plan);
}
@@ -245,7 +245,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
public PhoenixResultSet call() throws SQLException {
final long startTime = System.currentTimeMillis();
try {
- QueryPlan plan = stmt.compilePlan(PhoenixStatement.this, Sequence.ValueOp.RESERVE_SEQUENCE);
+ QueryPlan plan = stmt.compilePlan(PhoenixStatement.this, Sequence.ValueOp.VALIDATE_SEQUENCE);
plan = connection.getQueryServices().getOptimizer().optimize(
PhoenixStatement.this, plan);
// this will create its own trace internally, so we don't wrap this
@@ -303,7 +303,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
// since they'd update data directly from coprocessors, and should thus operate on
// the latest state
try {
- MutationPlan plan = stmt.compilePlan(PhoenixStatement.this, Sequence.ValueOp.RESERVE_SEQUENCE);
+ MutationPlan plan = stmt.compilePlan(PhoenixStatement.this, Sequence.ValueOp.VALIDATE_SEQUENCE);
MutationState state = plan.execute();
connection.getMutationState().join(state);
if (connection.getAutoCommit()) {
@@ -1203,14 +1203,14 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
if (stmt.getOperation().isMutation()) {
throw new ExecuteQueryNotApplicableException(query);
}
- return stmt.compilePlan(this, Sequence.ValueOp.RESERVE_SEQUENCE);
+ return stmt.compilePlan(this, Sequence.ValueOp.VALIDATE_SEQUENCE);
}
public MutationPlan compileMutation(CompilableStatement stmt, String query) throws SQLException {
if (!stmt.getOperation().isMutation()) {
throw new ExecuteUpdateNotApplicableException(query);
}
- return stmt.compilePlan(this, Sequence.ValueOp.RESERVE_SEQUENCE);
+ return stmt.compilePlan(this, Sequence.ValueOp.VALIDATE_SEQUENCE);
}
public MutationPlan compileMutation(String sql) throws SQLException {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
index 44359a7..49b14c6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
@@ -310,11 +310,11 @@ public class ParseNodeFactory {
}
public SequenceValueParseNode currentValueFor(TableName tableName) {
- return new SequenceValueParseNode(tableName, SequenceValueParseNode.Op.CURRENT_VALUE);
+ return new SequenceValueParseNode(tableName, SequenceValueParseNode.Op.CURRENT_VALUE, null);
}
- public SequenceValueParseNode nextValueFor(TableName tableName) {
- return new SequenceValueParseNode(tableName, SequenceValueParseNode.Op.NEXT_VALUE);
+ public SequenceValueParseNode nextValueFor(TableName tableName, ParseNode numToAllocateNode) {
+ return new SequenceValueParseNode(tableName, SequenceValueParseNode.Op.NEXT_VALUE, numToAllocateNode);
}
public AddColumnStatement addColumn(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, ListMultimap<String,Pair<String,Object>> props) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/parse/SequenceValueParseNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/SequenceValueParseNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/SequenceValueParseNode.java
index a5d60fe..1fc670c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/SequenceValueParseNode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/SequenceValueParseNode.java
@@ -39,10 +39,16 @@ public class SequenceValueParseNode extends TerminalParseNode {
}
private final TableName tableName;
private final Op op;
+ private final ParseNode numToAllocate;
- public SequenceValueParseNode(TableName tableName, Op op) {
+ public SequenceValueParseNode(TableName tableName, Op op, ParseNode numToAllocate) {
this.tableName = tableName;
this.op = op;
+ this.numToAllocate = numToAllocate;
+ }
+
+ public ParseNode getNumToAllocateNode() {
+ return numToAllocate;
}
@Override
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3b1bfa0d/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java
index dc51b10..3b53309 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java
@@ -40,6 +40,7 @@ import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.Sequence;
+import org.apache.phoenix.schema.SequenceAllocation;
import org.apache.phoenix.schema.SequenceKey;
import org.apache.phoenix.schema.stats.PTableStats;
@@ -91,8 +92,8 @@ public interface ConnectionQueryServices extends QueryServices, MetaDataMutated
long createSequence(String tenantId, String schemaName, String sequenceName, long startWith, long incrementBy, long cacheSize, long minValue, long maxValue, boolean cycle, long timestamp) throws SQLException;
long dropSequence(String tenantId, String schemaName, String sequenceName, long timestamp) throws SQLException;
- void validateSequences(List<SequenceKey> sequenceKeys, long timestamp, long[] values, SQLException[] exceptions, Sequence.ValueOp action) throws SQLException;
- void incrementSequences(List<SequenceKey> sequenceKeys, long timestamp, long[] values, SQLException[] exceptions) throws SQLException;
+ void validateSequences(List<SequenceAllocation> sequenceAllocations, long timestamp, long[] values, SQLException[] exceptions, Sequence.ValueOp action) throws SQLException;
+ void incrementSequences(List<SequenceAllocation> sequenceAllocation, long timestamp, long[] values, SQLException[] exceptions) throws SQLException;
long currentSequenceValue(SequenceKey sequenceKey, long timestamp) throws SQLException;
void returnSequences(List<SequenceKey> sequenceKeys, long timestamp, SQLException[] exceptions) throws SQLException;