You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by jd...@apache.org on 2016/07/25 17:15:35 UTC
[30/36] incubator-kudu git commit: [java-client] repackage to
org.apache.kudu (Part 1)
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITImportCsv.java
----------------------------------------------------------------------
diff --git a/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITImportCsv.java b/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITImportCsv.java
deleted file mode 100644
index d7b8352..0000000
--- a/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITImportCsv.java
+++ /dev/null
@@ -1,123 +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.kududb.mapreduce.tools;
-
-import org.kududb.ColumnSchema;
-import org.kududb.Schema;
-import org.kududb.Type;
-import org.kududb.mapreduce.CommandLineParser;
-import org.kududb.mapreduce.HadoopTestingUtility;
-import org.kududb.client.BaseKuduTest;
-import org.kududb.client.CreateTableOptions;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.mapreduce.Job;
-import org.apache.hadoop.util.GenericOptionsParser;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import com.google.common.collect.ImmutableList;
-
-public class ITImportCsv extends BaseKuduTest {
-
- private static final String TABLE_NAME =
- ITImportCsv.class.getName() + "-" + System.currentTimeMillis();
-
- private static final HadoopTestingUtility HADOOP_UTIL = new HadoopTestingUtility();
-
- private static Schema schema;
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- BaseKuduTest.setUpBeforeClass();
-
- ArrayList<ColumnSchema> columns = new ArrayList<ColumnSchema>(4);
- columns.add(new ColumnSchema.ColumnSchemaBuilder("key", Type.INT32)
- .key(true)
- .build());
- columns.add(new ColumnSchema.ColumnSchemaBuilder("column1_i", Type.INT32)
- .build());
- columns.add(new ColumnSchema.ColumnSchemaBuilder("column2_d", Type.DOUBLE)
- .build());
- columns.add(new ColumnSchema.ColumnSchemaBuilder("column3_s", Type.STRING)
- .nullable(true)
- .build());
- columns.add(new ColumnSchema.ColumnSchemaBuilder("column4_b", Type.BOOL)
- .build());
- schema = new Schema(columns);
-
- createTable(TABLE_NAME, schema,
- new CreateTableOptions().setRangePartitionColumns(ImmutableList.of("key")));
- }
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- try {
- BaseKuduTest.tearDownAfterClass();
- } finally {
- HADOOP_UTIL.cleanup();
- }
- }
-
- @Test
- public void test() throws Exception {
- Configuration conf = new Configuration();
- String testHome =
- HADOOP_UTIL.setupAndGetTestDir(ITImportCsv.class.getName(), conf).getAbsolutePath();
-
- // Create a 2 lines input file
- File data = new File(testHome, "data.csv");
- writeCsvFile(data);
-
- StringBuilder sb = new StringBuilder();
- for (ColumnSchema col : schema.getColumns()) {
- sb.append(col.getName());
- sb.append(",");
- }
- sb.deleteCharAt(sb.length() - 1);
- String[] args = new String[] {
- "-D" + CommandLineParser.MASTER_ADDRESSES_KEY + "=" + getMasterAddresses(),
- sb.toString(), TABLE_NAME, data.toString()};
-
- GenericOptionsParser parser = new GenericOptionsParser(conf, args);
- Job job = ImportCsv.createSubmittableJob(parser.getConfiguration(), parser.getRemainingArgs());
- assertTrue("Test job did not end properly", job.waitForCompletion(true));
-
- assertEquals(1, job.getCounters().findCounter(ImportCsv.Counters.BAD_LINES).getValue());
-
- assertEquals(3, countRowsInScan(
- client.newScannerBuilder(openTable(TABLE_NAME)).build()));
- // TODO: should verify the actual returned rows, not just the count!
- }
-
- private void writeCsvFile(File data) throws IOException {
- FileOutputStream fos = new FileOutputStream(data);
- fos.write("1\t3\t2.3\tsome string\ttrue\n".getBytes());
- fos.write("2\t5\t4.5\tsome more\tfalse\n".getBytes());
- fos.write("3\t7\twait this is not a double\tbad row\ttrue\n".getBytes());
- fos.write("4\t9\t10\ttrailing separator isn't bad mkay?\ttrue\t\n".getBytes());
- fos.close();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITIntegrationTestBigLinkedList.java
----------------------------------------------------------------------
diff --git a/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITIntegrationTestBigLinkedList.java b/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITIntegrationTestBigLinkedList.java
deleted file mode 100644
index 311c5ee..0000000
--- a/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITIntegrationTestBigLinkedList.java
+++ /dev/null
@@ -1,69 +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.kududb.mapreduce.tools;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.util.ToolRunner;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.Test;
-import org.kududb.client.BaseKuduTest;
-import org.kududb.mapreduce.CommandLineParser;
-import org.kududb.mapreduce.HadoopTestingUtility;
-
-public class ITIntegrationTestBigLinkedList extends BaseKuduTest {
-
- private static final HadoopTestingUtility HADOOP_UTIL = new HadoopTestingUtility();
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- try {
- BaseKuduTest.tearDownAfterClass();
- } finally {
- HADOOP_UTIL.cleanup();
- }
- }
-
- @Test
- public void test() throws Exception {
- Configuration conf = new Configuration();
- HADOOP_UTIL.setupAndGetTestDir(
- ITIntegrationTestBigLinkedList.class.getName(),conf).getAbsolutePath();
-
- String[] args = new String[] {
- "-D" + CommandLineParser.MASTER_ADDRESSES_KEY + "=" + getMasterAddresses(),
- "Loop",
- "2", // Two iterations
- "1", // 1 mapper
- "2500", // 2.5k rows to insert
- "1", // 1 tablet
- "/tmp/itbll", // output dir
- "1", // 1 reduce
- "100", // create 100 columns
- "25", // wrap them together after 25 rows
- "0"
- };
- int ret = ToolRunner.run(new IntegrationTestBigLinkedList(), args);
- Assert.assertEquals(0, ret);
-
- args[2] = "1"; // Just one iteration this time
- args[10] = "5000"; // 2 * 2500 from previous run
- ret = ToolRunner.run(new IntegrationTestBigLinkedList(), args);
- Assert.assertEquals(0, ret);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITRowCounter.java
----------------------------------------------------------------------
diff --git a/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITRowCounter.java b/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITRowCounter.java
deleted file mode 100644
index 52984bb..0000000
--- a/java/kudu-client-tools/src/test/java/org/kududb/mapreduce/tools/ITRowCounter.java
+++ /dev/null
@@ -1,68 +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.kududb.mapreduce.tools;
-
-import org.kududb.mapreduce.CommandLineParser;
-import org.kududb.mapreduce.HadoopTestingUtility;
-import org.kududb.client.BaseKuduTest;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.mapreduce.Job;
-import org.apache.hadoop.util.GenericOptionsParser;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class ITRowCounter extends BaseKuduTest {
-
- private static final String TABLE_NAME =
- ITRowCounter.class.getName() + "-" + System.currentTimeMillis();
-
- private static final HadoopTestingUtility HADOOP_UTIL = new HadoopTestingUtility();
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- BaseKuduTest.setUpBeforeClass();
- }
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- try {
- BaseKuduTest.tearDownAfterClass();
- } finally {
- HADOOP_UTIL.cleanup();
- }
- }
-
- @Test
- public void test() throws Exception {
- Configuration conf = new Configuration();
- HADOOP_UTIL.setupAndGetTestDir(ITRowCounter.class.getName(), conf).getAbsolutePath();
-
- createFourTabletsTableWithNineRows(TABLE_NAME);
-
- String[] args = new String[] {
- "-D" + CommandLineParser.MASTER_ADDRESSES_KEY + "=" + getMasterAddresses(), TABLE_NAME};
- GenericOptionsParser parser = new GenericOptionsParser(conf, args);
- Job job = RowCounter.createSubmittableJob(parser.getConfiguration(), parser.getRemainingArgs());
- assertTrue("Job did not end properly", job.waitForCompletion(true));
-
- assertEquals(9, job.getCounters().findCounter(RowCounter.Counters.ROWS).getValue());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/main/java/org/apache/kudu/ColumnSchema.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/ColumnSchema.java b/java/kudu-client/src/main/java/org/apache/kudu/ColumnSchema.java
new file mode 100644
index 0000000..c3c617d
--- /dev/null
+++ b/java/kudu-client/src/main/java/org/apache/kudu/ColumnSchema.java
@@ -0,0 +1,301 @@
+// 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.kududb;
+
+import org.kududb.Common.CompressionType;
+import org.kududb.Common.EncodingType;
+import org.kududb.annotations.InterfaceAudience;
+import org.kududb.annotations.InterfaceStability;
+
+/**
+ * Represents a Kudu Table column. Use {@link ColumnSchema.ColumnSchemaBuilder} in order to
+ * create columns.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public class ColumnSchema {
+
+ private final String name;
+ private final Type type;
+ private final boolean key;
+ private final boolean nullable;
+ private final Object defaultValue;
+ private final int desiredBlockSize;
+ private final Encoding encoding;
+ private final CompressionAlgorithm compressionAlgorithm;
+
+ /**
+ * Specifies the encoding of data for a column on disk.
+ * Not all encodings are available for all data types.
+ * Refer to the Kudu documentation for more information on each encoding.
+ */
+ public enum Encoding {
+ UNKNOWN(EncodingType.UNKNOWN_ENCODING),
+ AUTO_ENCODING(EncodingType.AUTO_ENCODING),
+ PLAIN_ENCODING(EncodingType.PLAIN_ENCODING),
+ PREFIX_ENCODING(EncodingType.PREFIX_ENCODING),
+ GROUP_VARINT(EncodingType.GROUP_VARINT),
+ RLE(EncodingType.RLE),
+ DICT_ENCODING(EncodingType.DICT_ENCODING),
+ BIT_SHUFFLE(EncodingType.BIT_SHUFFLE);
+
+ final EncodingType internalPbType;
+
+ Encoding(EncodingType internalPbType) {
+ this.internalPbType = internalPbType;
+ }
+
+ @InterfaceAudience.Private
+ public EncodingType getInternalPbType() {
+ return internalPbType;
+ }
+ };
+
+ /**
+ * Specifies the compression algorithm of data for a column on disk.
+ */
+ public enum CompressionAlgorithm {
+ UNKNOWN(CompressionType.UNKNOWN_COMPRESSION),
+ DEFAULT_COMPRESSION(CompressionType.DEFAULT_COMPRESSION),
+ NO_COMPRESSION(CompressionType.NO_COMPRESSION),
+ SNAPPY(CompressionType.SNAPPY),
+ LZ4(CompressionType.LZ4),
+ ZLIB(CompressionType.ZLIB);
+
+ final CompressionType internalPbType;
+
+ CompressionAlgorithm(CompressionType internalPbType) {
+ this.internalPbType = internalPbType;
+ }
+
+ @InterfaceAudience.Private
+ public CompressionType getInternalPbType() {
+ return internalPbType;
+ }
+ };
+
+ private ColumnSchema(String name, Type type, boolean key, boolean nullable,
+ Object defaultValue, int desiredBlockSize, Encoding encoding,
+ CompressionAlgorithm compressionAlgorithm) {
+ this.name = name;
+ this.type = type;
+ this.key = key;
+ this.nullable = nullable;
+ this.defaultValue = defaultValue;
+ this.desiredBlockSize = desiredBlockSize;
+ this.encoding = encoding;
+ this.compressionAlgorithm = compressionAlgorithm;
+ }
+
+ /**
+ * Get the column's Type
+ * @return the type
+ */
+ public Type getType() {
+ return type;
+ }
+
+ /**
+ * Get the column's name
+ * @return A string representation of the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Answers if the column part of the key
+ * @return true if the column is part of the key, else false
+ */
+ public boolean isKey() {
+ return key;
+ }
+
+ /**
+ * Answers if the column can be set to null
+ * @return true if it can be set to null, else false
+ */
+ public boolean isNullable() {
+ return nullable;
+ }
+
+ /**
+ * The Java object representation of the default value that's read
+ * @return the default read value
+ */
+ public Object getDefaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * Gets the desired block size for this column.
+ * If no block size has been explicitly specified for this column,
+ * returns 0 to indicate that the server-side default will be used.
+ *
+ * @return the block size, in bytes, or 0 if none has been configured.
+ */
+ public int getDesiredBlockSize() {
+ return desiredBlockSize;
+ }
+
+ /**
+ * Return the encoding of this column, or null if it is not known.
+ */
+ public Encoding getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Return the compression algorithm of this column, or null if it is not known.
+ */
+ public CompressionAlgorithm getCompressionAlgorithm() {
+ return compressionAlgorithm;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ColumnSchema that = (ColumnSchema) o;
+
+ if (key != that.key) return false;
+ if (!name.equals(that.name)) return false;
+ if (!type.equals(that.type)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name.hashCode();
+ result = 31 * result + type.hashCode();
+ result = 31 * result + (key ? 1 : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Column name: " + name + ", type: " + type.getName();
+ }
+
+ /**
+ * Builder for ColumnSchema.
+ */
+ public static class ColumnSchemaBuilder {
+ private final String name;
+ private final Type type;
+ private boolean key = false;
+ private boolean nullable = false;
+ private Object defaultValue = null;
+ private int blockSize = 0;
+ private Encoding encoding = null;
+ private CompressionAlgorithm compressionAlgorithm = null;
+
+ /**
+ * Constructor for the required parameters.
+ * @param name column's name
+ * @param type column's type
+ */
+ public ColumnSchemaBuilder(String name, Type type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ /**
+ * Sets if the column is part of the row key. False by default.
+ * @param key a boolean that indicates if the column is part of the key
+ * @return this instance
+ */
+ public ColumnSchemaBuilder key(boolean key) {
+ this.key = key;
+ return this;
+ }
+
+ /**
+ * Marks the column as allowing null values. False by default.
+ * @param nullable a boolean that indicates if the column allows null values
+ * @return this instance
+ */
+ public ColumnSchemaBuilder nullable(boolean nullable) {
+ this.nullable = nullable;
+ return this;
+ }
+
+ /**
+ * Sets the default value that will be read from the column. Null by default.
+ * @param defaultValue a Java object representation of the default value that's read
+ * @return this instance
+ */
+ public ColumnSchemaBuilder defaultValue(Object defaultValue) {
+ this.defaultValue = defaultValue;
+ return this;
+ }
+
+ /**
+ * Set the desired block size for this column.
+ *
+ * This is the number of bytes of user data packed per block on disk, and
+ * represents the unit of IO when reading this column. Larger values
+ * may improve scan performance, particularly on spinning media. Smaller
+ * values may improve random access performance, particularly for workloads
+ * that have high cache hit rates or operate on fast storage such as SSD.
+ *
+ * Note that the block size specified here corresponds to uncompressed data.
+ * The actual size of the unit read from disk may be smaller if
+ * compression is enabled.
+ *
+ * It's recommended that this not be set any lower than 4096 (4KB) or higher
+ * than 1048576 (1MB).
+ * @param blockSize the desired block size, in bytes
+ * @return this instance
+ * <!-- TODO(KUDU-1107): move the above info to docs -->
+ */
+ public ColumnSchemaBuilder desiredBlockSize(int blockSize) {
+ this.blockSize = blockSize;
+ return this;
+ }
+
+ /**
+ * Set the block encoding for this column. See the documentation for the list
+ * of valid options.
+ */
+ public ColumnSchemaBuilder encoding(Encoding encoding) {
+ this.encoding = encoding;
+ return this;
+ }
+
+ /**
+ * Set the compression algorithm for this column. See the documentation for the list
+ * of valid options.
+ */
+ public ColumnSchemaBuilder compressionAlgorithm(CompressionAlgorithm compressionAlgorithm) {
+ this.compressionAlgorithm = compressionAlgorithm;
+ return this;
+ }
+
+ /**
+ * Builds a {@link ColumnSchema} using the passed parameters.
+ * @return a new {@link ColumnSchema}
+ */
+ public ColumnSchema build() {
+ return new ColumnSchema(name, type,
+ key, nullable, defaultValue,
+ blockSize, encoding, compressionAlgorithm);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/main/java/org/apache/kudu/Schema.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/Schema.java b/java/kudu-client/src/main/java/org/apache/kudu/Schema.java
new file mode 100644
index 0000000..17e7798
--- /dev/null
+++ b/java/kudu-client/src/main/java/org/apache/kudu/Schema.java
@@ -0,0 +1,291 @@
+// 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.kududb;
+
+import com.google.common.collect.ImmutableList;
+import org.kududb.annotations.InterfaceAudience;
+import org.kududb.annotations.InterfaceStability;
+import org.kududb.client.Bytes;
+import org.kududb.client.PartialRow;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents table's schema which is essentially a list of columns.
+ * This class offers a few utility methods for querying it.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public class Schema {
+
+ /**
+ * Mapping of column index to column.
+ */
+ private final List<ColumnSchema> columnsByIndex;
+
+ /**
+ * The primary key columns.
+ */
+ private final List<ColumnSchema> primaryKeyColumns = new ArrayList<>();
+
+ /**
+ * Mapping of column name to index.
+ */
+ private final Map<String, Integer> columnsByName;
+
+ /**
+ * Mapping of column ID to index, or null if the schema does not have assigned column IDs.
+ */
+ private final Map<Integer, Integer> columnsById;
+
+ /**
+ * Mapping of column index to backing byte array offset.
+ */
+ private final int[] columnOffsets;
+
+ private final int varLengthColumnCount;
+ private final int rowSize;
+ private final boolean hasNullableColumns;
+
+ /**
+ * Constructs a schema using the specified columns and does some internal accounting
+ * @param columns the columns in index order
+ * @throws IllegalArgumentException If the key columns aren't specified first
+ *
+ * See {@code ColumnPBsToSchema()} in {@code src/kudu/common/wire_protocol.cc}
+ */
+ public Schema(List<ColumnSchema> columns) {
+ this(columns, null);
+ }
+
+ /**
+ * Constructs a schema using the specified columns and IDs.
+ *
+ * This is not a stable API, prefer using {@link Schema#Schema(List)} to create a new schema.
+ *
+ * @param columns the columns in index order
+ * @param columnIds the column ids of the provided columns, or null
+ * @throws IllegalArgumentException If the primary key columns aren't specified first
+ * @throws IllegalArgumentException If the column ids length does not match the columns length
+ *
+ * See {@code ColumnPBsToSchema()} in {@code src/kudu/common/wire_protocol.cc}
+ */
+ public Schema(List<ColumnSchema> columns, List<Integer> columnIds) {
+ boolean hasColumnIds = columnIds != null;
+ if (hasColumnIds && columns.size() != columnIds.size()) {
+ throw new IllegalArgumentException(
+ "Schema must be constructed with all column IDs, or none.");
+ }
+
+ this.columnsByIndex = ImmutableList.copyOf(columns);
+ int varLenCnt = 0;
+ this.columnOffsets = new int[columns.size()];
+ this.columnsByName = new HashMap<>(columns.size());
+ this.columnsById = hasColumnIds ? new HashMap<Integer, Integer>(columnIds.size()) : null;
+ int offset = 0;
+ boolean hasNulls = false;
+ // pre-compute a few counts and offsets
+ for (int index = 0; index < columns.size(); index++) {
+ final ColumnSchema column = columns.get(index);
+ if (column.isKey()) {
+ primaryKeyColumns.add(column);
+ }
+
+ hasNulls |= column.isNullable();
+ columnOffsets[index] = offset;
+ offset += column.getType().getSize();
+ if (this.columnsByName.put(column.getName(), index) != null) {
+ throw new IllegalArgumentException(
+ String.format("Column names must be unique: %s", columns));
+ }
+ if (column.getType() == Type.STRING || column.getType() == Type.BINARY) {
+ varLenCnt++;
+ }
+
+ if (hasColumnIds) {
+ if (this.columnsById.put(columnIds.get(index), index) != null) {
+ throw new IllegalArgumentException(
+ String.format("Column IDs must be unique: %s", columnIds));
+ }
+ }
+ }
+
+ this.hasNullableColumns = hasNulls;
+ this.varLengthColumnCount = varLenCnt;
+ this.rowSize = getRowSize(this.columnsByIndex);
+ }
+
+ /**
+ * Get the list of columns used to create this schema
+ * @return list of columns
+ */
+ public List<ColumnSchema> getColumns() {
+ return this.columnsByIndex;
+ }
+
+ /**
+ * Get the count of columns with variable length (BINARY/STRING) in
+ * this schema.
+ * @return strings count
+ */
+ public int getVarLengthColumnCount() {
+ return this.varLengthColumnCount;
+ }
+
+ /**
+ * Get the size a row built using this schema would be
+ * @return size in bytes
+ */
+ public int getRowSize() {
+ return this.rowSize;
+ }
+
+ /**
+ * Get the index at which this column can be found in the backing byte array
+ * @param idx column's index
+ * @return column's offset
+ */
+ public int getColumnOffset(int idx) {
+ return this.columnOffsets[idx];
+ }
+
+ /**
+ * Get the index for the provided column name.
+ * @param columnName column to search for
+ * @return an index in the schema
+ */
+ public int getColumnIndex(String columnName) {
+ Integer index = this.columnsByName.get(columnName);
+ if (index == null) {
+ throw new IllegalArgumentException(
+ String.format("Unknown column: %s", columnName));
+ }
+ return index;
+ }
+
+ /**
+ * Get the column at the specified index in the original list
+ * @param idx column's index
+ * @return the column
+ */
+ public ColumnSchema getColumnByIndex(int idx) {
+ return this.columnsByIndex.get(idx);
+ }
+
+ /**
+ * Get the column index of the column with the provided ID.
+ * This method is not part of the stable API.
+ * @param columnId the column id of the column
+ * @return the column index of the column.
+ */
+ public int getColumnIndex(int columnId) {
+ if (!hasColumnIds()) throw new IllegalStateException("Schema does not have Column IDs");
+ Integer index = this.columnsById.get(columnId);
+ if (index == null) throw new IllegalArgumentException(
+ String.format("Unknown column id: %s", columnId));
+ return index;
+ }
+
+ /**
+ * Get the column associated with the specified name
+ * @param columnName column's name
+ * @return the column
+ */
+ public ColumnSchema getColumn(String columnName) {
+ return columnsByIndex.get(getColumnIndex(columnName));
+ }
+
+ /**
+ * Get the count of columns in this schema
+ * @return count of columns
+ */
+ public int getColumnCount() {
+ return this.columnsByIndex.size();
+ }
+
+ /**
+ * Get the count of columns that are part of the primary key.
+ * @return count of primary key columns.
+ */
+ public int getPrimaryKeyColumnCount() {
+ return this.primaryKeyColumns.size();
+ }
+
+ /**
+ * Get the primary key columns.
+ * @return the primary key columns.
+ */
+ public List<ColumnSchema> getPrimaryKeyColumns() {
+ return primaryKeyColumns;
+ }
+
+ /**
+ * Get a schema that only contains the columns which are part of the key
+ * @return new schema with only the keys
+ */
+ public Schema getRowKeyProjection() {
+ return new Schema(primaryKeyColumns);
+ }
+
+ /**
+ * Tells if there's at least one nullable column
+ * @return true if at least one column is nullable, else false.
+ */
+ public boolean hasNullableColumns() {
+ return this.hasNullableColumns;
+ }
+
+ /**
+ * Tells whether this schema includes IDs for columns. A schema created by a client as part of
+ * table creation will not include IDs, but schemas for open tables will include IDs.
+ * This method is not part of the stable API.
+ *
+ * @return whether this schema includes column IDs.
+ */
+ public boolean hasColumnIds() {
+ return columnsById != null;
+ }
+
+ /**
+ * Gives the size in bytes for a single row given the specified schema
+ * @param columns the row's columns
+ * @return row size in bytes
+ */
+ private static int getRowSize(List<ColumnSchema> columns) {
+ int totalSize = 0;
+ boolean hasNullables = false;
+ for (ColumnSchema column : columns) {
+ totalSize += column.getType().getSize();
+ hasNullables |= column.isNullable();
+ }
+ if (hasNullables) {
+ totalSize += Bytes.getBitSetSize(columns.size());
+ }
+ return totalSize;
+ }
+
+ /**
+ * Creates a new partial row for the schema.
+ * @return a new partial row
+ */
+ public PartialRow newPartialRow() {
+ return new PartialRow(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/main/java/org/apache/kudu/Type.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/Type.java b/java/kudu-client/src/main/java/org/apache/kudu/Type.java
new file mode 100644
index 0000000..fd23835
--- /dev/null
+++ b/java/kudu-client/src/main/java/org/apache/kudu/Type.java
@@ -0,0 +1,136 @@
+// 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.kududb;
+
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
+import com.google.common.primitives.Shorts;
+import org.kududb.annotations.InterfaceAudience;
+import org.kududb.annotations.InterfaceStability;
+
+import static org.kududb.Common.DataType;
+
+/**
+ * Describes all the types available to build table schemas.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public enum Type {
+
+ INT8 (DataType.INT8, "int8"),
+ INT16 (DataType.INT16, "int16"),
+ INT32 (DataType.INT32, "int32"),
+ INT64 (DataType.INT64, "int64"),
+ BINARY (DataType.BINARY, "binary"),
+ STRING (DataType.STRING, "string"),
+ BOOL (DataType.BOOL, "bool"),
+ FLOAT (DataType.FLOAT, "float"),
+ DOUBLE (DataType.DOUBLE, "double"),
+ TIMESTAMP (DataType.TIMESTAMP, "timestamp");
+
+
+ private final DataType dataType;
+ private final String name;
+ private final int size;
+
+ /**
+ * Private constructor used to pre-create the types
+ * @param dataType DataType from the common's pb
+ * @param name string representation of the type
+ */
+ private Type(DataType dataType, String name) {
+ this.dataType = dataType;
+ this.name = name;
+ this.size = getTypeSize(this.dataType);
+ }
+
+ /**
+ * Get the data type from the common's pb
+ * @return A DataType
+ */
+ public DataType getDataType() {
+ return this.dataType;
+ }
+
+ /**
+ * Get the string representation of this type
+ * @return The type's name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * The size of this type on the wire
+ * @return A size
+ */
+ public int getSize() {
+ return this.size;
+ }
+
+ @Override
+ public String toString() {
+ return "Type: " + this.name + ", size: " + this.size;
+ }
+
+ /**
+ * Gives the size in bytes for a given DataType, as per the pb specification
+ * @param type pb type
+ * @return size in bytes
+ */
+ static int getTypeSize(DataType type) {
+ switch (type) {
+ case STRING:
+ case BINARY: return 8 + 8; // offset then string length
+ case BOOL:
+ case INT8: return 1;
+ case INT16: return Shorts.BYTES;
+ case INT32:
+ case FLOAT: return Ints.BYTES;
+ case INT64:
+ case DOUBLE:
+ case TIMESTAMP: return Longs.BYTES;
+ default: throw new IllegalArgumentException("The provided data type doesn't map" +
+ " to know any known one.");
+ }
+ }
+
+ /**
+ * Convert the pb DataType to a Type
+ * @param type DataType to convert
+ * @return a matching Type
+ */
+ public static Type getTypeForDataType(DataType type) {
+ switch (type) {
+ case STRING: return STRING;
+ case BINARY: return BINARY;
+ case BOOL: return BOOL;
+ case INT8: return INT8;
+ case INT16: return INT16;
+ case INT32: return INT32;
+ case INT64: return INT64;
+ case TIMESTAMP: return TIMESTAMP;
+ case FLOAT: return FLOAT;
+ case DOUBLE: return DOUBLE;
+ default:
+ throw new IllegalArgumentException("The provided data type doesn't map" +
+ " to know any known one: " + type.getDescriptorForType().getFullName());
+
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/main/java/org/apache/kudu/client/AbstractKuduScannerBuilder.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/AbstractKuduScannerBuilder.java b/java/kudu-client/src/main/java/org/apache/kudu/client/AbstractKuduScannerBuilder.java
new file mode 100644
index 0000000..b1b0712
--- /dev/null
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/AbstractKuduScannerBuilder.java
@@ -0,0 +1,338 @@
+// 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.kududb.client;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableList;
+import org.kududb.Common;
+import org.kududb.annotations.InterfaceAudience;
+import org.kududb.annotations.InterfaceStability;
+import org.kududb.tserver.Tserver;
+import org.kududb.util.HybridTimeUtil;
+
+/**
+ * Abstract class to extend in order to create builders for scanners.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public abstract class AbstractKuduScannerBuilder
+ <S extends AbstractKuduScannerBuilder<? super S, T>, T> {
+ final AsyncKuduClient client;
+ final KuduTable table;
+
+ /** Map of column name to predicate */
+ final Map<String, KuduPredicate> predicates = new HashMap<>();
+
+ AsyncKuduScanner.ReadMode readMode = AsyncKuduScanner.ReadMode.READ_LATEST;
+ Common.OrderMode orderMode = Common.OrderMode.UNORDERED;
+ int batchSizeBytes = 1024*1024;
+ long limit = Long.MAX_VALUE;
+ boolean prefetching = false;
+ boolean cacheBlocks = true;
+ long htTimestamp = AsyncKuduClient.NO_TIMESTAMP;
+ byte[] lowerBoundPrimaryKey = AsyncKuduClient.EMPTY_ARRAY;
+ byte[] upperBoundPrimaryKey = AsyncKuduClient.EMPTY_ARRAY;
+ byte[] lowerBoundPartitionKey = AsyncKuduClient.EMPTY_ARRAY;
+ byte[] upperBoundPartitionKey = AsyncKuduClient.EMPTY_ARRAY;
+ List<String> projectedColumnNames = null;
+ List<Integer> projectedColumnIndexes = null;
+ long scanRequestTimeout;
+
+ AbstractKuduScannerBuilder(AsyncKuduClient client, KuduTable table) {
+ this.client = client;
+ this.table = table;
+ this.scanRequestTimeout = client.getDefaultOperationTimeoutMs();
+ }
+
+ /**
+ * Sets the read mode, the default is to read the latest values.
+ * @param readMode a read mode for the scanner
+ * @return this instance
+ */
+ public S readMode(AsyncKuduScanner.ReadMode readMode) {
+ this.readMode = readMode;
+ return (S) this;
+ }
+
+ /**
+ * Return scan results in primary key sorted order.
+ *
+ * If the table is hash partitioned, the scan must have an equality predicate
+ * on all hashed columns.
+ *
+ * Package private until proper hash partitioning equality predicate checks
+ * are in place.
+ *
+ * Disabled by default.
+ * @return this instance
+ */
+ @InterfaceAudience.Private
+ @InterfaceStability.Unstable
+ S sortResultsByPrimaryKey() {
+ orderMode = Common.OrderMode.ORDERED;
+ readMode = AsyncKuduScanner.ReadMode.READ_AT_SNAPSHOT;
+ return (S) this;
+ }
+
+ /**
+ * Adds a predicate for a column.
+ * @param predicate predicate for a column to add
+ * @return this instance
+ * @deprecated use {@link #addPredicate(KuduPredicate)}
+ */
+ @Deprecated
+ public S addColumnRangePredicate(ColumnRangePredicate predicate) {
+ return addPredicate(predicate.toKuduPredicate());
+ }
+
+ /**
+ * Adds a list of predicates in their raw format,
+ * as given by {@link ColumnRangePredicate#toByteArray(List)}.
+ * @param predicateBytes predicates to add
+ * @return this instance
+ * @throws IllegalArgumentException thrown when the passed bytes aren't valid
+ * @deprecated use {@link #addPredicate}
+ */
+ @Deprecated
+ public S addColumnRangePredicatesRaw(byte[] predicateBytes) {
+ for (Tserver.ColumnRangePredicatePB pb : ColumnRangePredicate.fromByteArray(predicateBytes)) {
+ addPredicate(ColumnRangePredicate.fromPb(pb).toKuduPredicate());
+ }
+ return (S) this;
+ }
+
+ /**
+ * Adds a predicate to the scan.
+ * @param predicate predicate to add
+ * @return this instance
+ */
+ public S addPredicate(KuduPredicate predicate) {
+ String columnName = predicate.getColumn().getName();
+ KuduPredicate existing = predicates.get(columnName);
+ if (existing == null) {
+ predicates.put(columnName, predicate);
+ } else {
+ predicates.put(columnName, existing.merge(predicate));
+ }
+ return (S) this;
+ }
+
+ /**
+ * Set which columns will be read by the Scanner.
+ * Calling this method after {@link #setProjectedColumnIndexes(List)} will reset the projected
+ * columns to those specified in {@code columnNames}.
+ * @param columnNames the names of columns to read, or 'null' to read all columns
+ * (the default)
+ */
+ public S setProjectedColumnNames(List<String> columnNames) {
+ projectedColumnIndexes = null;
+ if (columnNames != null) {
+ projectedColumnNames = ImmutableList.copyOf(columnNames);
+ } else {
+ projectedColumnNames = null;
+ }
+ return (S) this;
+ }
+
+ /**
+ * Set which columns will be read by the Scanner.
+ * Calling this method after {@link #setProjectedColumnNames(List)} will reset the projected
+ * columns to those specified in {@code columnIndexes}.
+ * @param columnIndexes the indexes of columns to read, or 'null' to read all columns
+ * (the default)
+ */
+ public S setProjectedColumnIndexes(List<Integer> columnIndexes) {
+ projectedColumnNames = null;
+ if (columnIndexes != null) {
+ projectedColumnIndexes = ImmutableList.copyOf(columnIndexes);
+ } else {
+ projectedColumnIndexes = null;
+ }
+ return (S) this;
+ }
+
+ /**
+ * Sets the maximum number of bytes returned by the scanner, on each batch. The default is 1MB.
+ * <p>
+ * Kudu may actually return more than this many bytes because it will not
+ * truncate a rowResult in the middle.
+ * @param batchSizeBytes a strictly positive number of bytes
+ * @return this instance
+ */
+ public S batchSizeBytes(int batchSizeBytes) {
+ this.batchSizeBytes = batchSizeBytes;
+ return (S) this;
+ }
+
+ /**
+ * Sets a limit on the number of rows that will be returned by the scanner. There's no limit
+ * by default.
+ * @param limit a positive long
+ * @return this instance
+ */
+ public S limit(long limit) {
+ this.limit = limit;
+ return (S) this;
+ }
+
+ /**
+ * Enables prefetching of rows for the scanner, i.e. whether to send a request for more data
+ * to the server immediately after we receive a response (instead of waiting for the user
+ * to call {@code nextRows()}). Disabled by default.
+ * NOTE: This is risky until KUDU-1260 is resolved.
+ * @param prefetching a boolean that indicates if the scanner should prefetch rows
+ * @return this instance
+ */
+ public S prefetching(boolean prefetching) {
+ this.prefetching = prefetching;
+ return (S) this;
+ }
+
+ /**
+ * Sets the block caching policy for the scanner. If true, scanned data blocks will be cached
+ * in memory and made available for future scans. Enabled by default.
+ * @param cacheBlocks a boolean that indicates if data blocks should be cached or not
+ * @return this instance
+ */
+ public S cacheBlocks(boolean cacheBlocks) {
+ this.cacheBlocks = cacheBlocks;
+ return (S) this;
+ }
+
+ /**
+ * Sets a previously encoded HT timestamp as a snapshot timestamp, for tests. None is used by
+ * default.
+ * Requires that the ReadMode is READ_AT_SNAPSHOT.
+ * @param htTimestamp a long representing a HybridClock-encoded timestamp
+ * @return this instance
+ * @throws IllegalArgumentException on build(), if the timestamp is less than 0 or if the
+ * read mode was not set to READ_AT_SNAPSHOT
+ */
+ @InterfaceAudience.Private
+ public S snapshotTimestampRaw(long htTimestamp) {
+ this.htTimestamp = htTimestamp;
+ return (S) this;
+ }
+
+ /**
+ * Sets the timestamp the scan must be executed at, in microseconds since the Unix epoch. None is
+ * used by default.
+ * Requires that the ReadMode is READ_AT_SNAPSHOT.
+ * @param timestamp a long representing an instant in microseconds since the unix epoch.
+ * @return this instance
+ * @throws IllegalArgumentException on build(), if the timestamp is less than 0 or if the
+ * read mode was not set to READ_AT_SNAPSHOT
+ */
+ public S snapshotTimestampMicros(long timestamp) {
+ this.htTimestamp = HybridTimeUtil.physicalAndLogicalToHTTimestamp(timestamp, 0);
+ return (S) this;
+ }
+
+ /**
+ * Sets how long each scan request to a server can last.
+ * Defaults to {@link KuduClient#getDefaultOperationTimeoutMs()}.
+ * @param scanRequestTimeout a long representing time in milliseconds
+ * @return this instance
+ */
+ public S scanRequestTimeout(long scanRequestTimeout) {
+ this.scanRequestTimeout = scanRequestTimeout;
+ return (S) this;
+ }
+
+ /**
+ * Add a lower bound (inclusive) primary key for the scan.
+ * If any bound is already added, this bound is intersected with that one.
+ * @param partialRow a partial row with specified key columns
+ * @return this instance
+ */
+ public S lowerBound(PartialRow partialRow) {
+ return lowerBoundRaw(partialRow.encodePrimaryKey());
+ }
+
+ /**
+ * Like lowerBoundPrimaryKey() but the encoded primary key is an opaque byte array obtained elsewhere.
+ * @param startPrimaryKey bytes containing an encoded start key
+ * @return this instance
+ * @deprecated use {@link #lowerBound(PartialRow)}
+ */
+ @Deprecated
+ public S lowerBoundRaw(byte[] startPrimaryKey) {
+ if (lowerBoundPrimaryKey == AsyncKuduClient.EMPTY_ARRAY ||
+ Bytes.memcmp(startPrimaryKey, lowerBoundPrimaryKey) > 0) {
+ this.lowerBoundPrimaryKey = startPrimaryKey;
+ }
+ return (S) this;
+ }
+
+ /**
+ * Add an upper bound (exclusive) primary key for the scan.
+ * If any bound is already added, this bound is intersected with that one.
+ * @param partialRow a partial row with specified key columns
+ * @return this instance
+ */
+ public S exclusiveUpperBound(PartialRow partialRow) {
+ return exclusiveUpperBoundRaw(partialRow.encodePrimaryKey());
+ }
+
+ /**
+ * Like exclusiveUpperBound() but the encoded primary key is an opaque byte array obtained elsewhere.
+ * @param endPrimaryKey bytes containing an encoded end key
+ * @return this instance
+ * @deprecated use {@link #exclusiveUpperBound(PartialRow)}
+ */
+ @Deprecated
+ public S exclusiveUpperBoundRaw(byte[] endPrimaryKey) {
+ if (upperBoundPrimaryKey == AsyncKuduClient.EMPTY_ARRAY ||
+ Bytes.memcmp(endPrimaryKey, upperBoundPrimaryKey) < 0) {
+ this.upperBoundPrimaryKey = endPrimaryKey;
+ }
+ return (S) this;
+ }
+
+ /**
+ * Set an encoded (inclusive) start partition key for the scan.
+ *
+ * @param partitionKey the encoded partition key
+ * @return this instance
+ */
+ @InterfaceAudience.LimitedPrivate("Impala")
+ public S lowerBoundPartitionKeyRaw(byte[] partitionKey) {
+ if (Bytes.memcmp(partitionKey, lowerBoundPartitionKey) > 0) {
+ this.lowerBoundPartitionKey = partitionKey;
+ }
+ return (S) this;
+ }
+
+ /**
+ * Set an encoded (exclusive) end partition key for the scan.
+ *
+ * @param partitionKey the encoded partition key
+ * @return this instance
+ */
+ @InterfaceAudience.LimitedPrivate("Impala")
+ public S exclusiveUpperBoundPartitionKeyRaw(byte[] partitionKey) {
+ if (upperBoundPartitionKey.length == 0 || Bytes.memcmp(partitionKey, upperBoundPartitionKey) < 0) {
+ this.upperBoundPartitionKey = partitionKey;
+ }
+ return (S) this;
+ }
+
+ public abstract T build();
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableOptions.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableOptions.java b/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableOptions.java
new file mode 100644
index 0000000..ecffb5e
--- /dev/null
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableOptions.java
@@ -0,0 +1,107 @@
+// 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.kududb.client;
+
+import org.kududb.ColumnSchema;
+import org.kududb.Type;
+import org.kududb.annotations.InterfaceAudience;
+import org.kududb.annotations.InterfaceStability;
+
+import static org.kududb.master.Master.AlterTableRequestPB;
+
+/**
+ * This builder must be used to alter a table. At least one change must be specified.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Unstable
+public class AlterTableOptions {
+
+ AlterTableRequestPB.Builder pb = AlterTableRequestPB.newBuilder();
+
+ /**
+ * Change a table's name.
+ * @param newName new table's name, must be used to check progress
+ * @return this instance
+ */
+ public AlterTableOptions renameTable(String newName) {
+ pb.setNewTableName(newName);
+ return this;
+ }
+
+ /**
+ * Add a new column that's not nullable.
+ * @param name name of the new column
+ * @param type type of the new column
+ * @param defaultVal default value used for the currently existing rows
+ * @return this instance
+ */
+ public AlterTableOptions addColumn(String name, Type type, Object defaultVal) {
+ if (defaultVal == null) {
+ throw new IllegalArgumentException("A new column must have a default value, " +
+ "use addNullableColumn() to add a NULLABLE column");
+ }
+ AlterTableRequestPB.Step.Builder step = pb.addAlterSchemaStepsBuilder();
+ step.setType(AlterTableRequestPB.StepType.ADD_COLUMN);
+ step.setAddColumn(AlterTableRequestPB.AddColumn.newBuilder().setSchema(ProtobufHelper
+ .columnToPb(new ColumnSchema.ColumnSchemaBuilder(name, type)
+ .defaultValue(defaultVal)
+ .build())));
+ return this;
+ }
+
+ /**
+ * Add a new column that's nullable, thus has no default value.
+ * @param name name of the new column
+ * @param type type of the new column
+ * @return this instance
+ */
+ public AlterTableOptions addNullableColumn(String name, Type type) {
+ AlterTableRequestPB.Step.Builder step = pb.addAlterSchemaStepsBuilder();
+ step.setType(AlterTableRequestPB.StepType.ADD_COLUMN);
+ step.setAddColumn(AlterTableRequestPB.AddColumn.newBuilder().setSchema(ProtobufHelper
+ .columnToPb(new ColumnSchema.ColumnSchemaBuilder(name, type)
+ .nullable(true)
+ .build())));
+ return this;
+ }
+
+ /**
+ * Drop a column.
+ * @param name name of the column
+ * @return this instance
+ */
+ public AlterTableOptions dropColumn(String name) {
+ AlterTableRequestPB.Step.Builder step = pb.addAlterSchemaStepsBuilder();
+ step.setType(AlterTableRequestPB.StepType.DROP_COLUMN);
+ step.setDropColumn(AlterTableRequestPB.DropColumn.newBuilder().setName(name));
+ return this;
+ }
+
+ /**
+ * Change the name of a column.
+ * @param oldName old column's name, must exist
+ * @param newName new name to use
+ * @return this instance
+ */
+ public AlterTableOptions renameColumn(String oldName, String newName) {
+ AlterTableRequestPB.Step.Builder step = pb.addAlterSchemaStepsBuilder();
+ step.setType(AlterTableRequestPB.StepType.RENAME_COLUMN);
+ step.setRenameColumn(AlterTableRequestPB.RenameColumn.newBuilder().setOldName(oldName)
+ .setNewName(newName));
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableRequest.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableRequest.java b/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableRequest.java
new file mode 100644
index 0000000..751290c
--- /dev/null
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableRequest.java
@@ -0,0 +1,70 @@
+// 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.kududb.client;
+
+import com.google.protobuf.Message;
+import org.kududb.annotations.InterfaceAudience;
+import org.kududb.util.Pair;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import static org.kududb.master.Master.*;
+
+/**
+ * RPC used to alter a table. When it returns it doesn't mean that the table is altered,
+ * a success just means that the master accepted it.
+ */
+@InterfaceAudience.Private
+class AlterTableRequest extends KuduRpc<AlterTableResponse> {
+
+ static final String ALTER_TABLE = "AlterTable";
+ private final String name;
+ private final AlterTableRequestPB.Builder builder;
+
+ AlterTableRequest(KuduTable masterTable, String name, AlterTableOptions ato) {
+ super(masterTable);
+ this.name = name;
+ this.builder = ato.pb;
+ }
+
+ @Override
+ ChannelBuffer serialize(Message header) {
+ assert header.isInitialized();
+ TableIdentifierPB tableID =
+ TableIdentifierPB.newBuilder().setTableName(name).build();
+ this.builder.setTable(tableID);
+ return toChannelBuffer(header, this.builder.build());
+ }
+
+ @Override
+ String serviceName() { return MASTER_SERVICE_NAME; }
+
+ @Override
+ String method() {
+ return ALTER_TABLE;
+ }
+
+ @Override
+ Pair<AlterTableResponse, Object> deserialize(final CallResponse callResponse,
+ String tsUUID) throws Exception {
+ final AlterTableResponsePB.Builder respBuilder = AlterTableResponsePB.newBuilder();
+ readProtobuf(callResponse.getPBMessage(), respBuilder);
+ AlterTableResponse response = new AlterTableResponse(deadlineTracker.getElapsedMillis(),
+ tsUUID);
+ return new Pair<AlterTableResponse, Object>(
+ response, respBuilder.hasError() ? respBuilder.getError() : null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableResponse.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableResponse.java b/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableResponse.java
new file mode 100644
index 0000000..7d1d581
--- /dev/null
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableResponse.java
@@ -0,0 +1,32 @@
+// 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.kududb.client;
+
+import org.kududb.annotations.InterfaceAudience;
+import org.kududb.annotations.InterfaceStability;
+
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public class AlterTableResponse extends KuduRpcResponse {
+
+ /**
+ * @param ellapsedMillis Time in milliseconds since RPC creation to now.
+ */
+ AlterTableResponse(long ellapsedMillis, String tsUUID) {
+ super(ellapsedMillis, tsUUID);
+ }
+}
\ No newline at end of file