Table column types

Ampool tables can store binary data (byte-array) in columns as well as various types of Java objects. You can assign one of the supported types to the columns when creating table. In case you do not specify type to a column the default is assumed as BINARY (i.e. byte-array). When you have assigned a type to the column, the APIs internally take care of serialization and deserialization wherever required.

The MTable types can be divided into two categories:

  • Basic types – these types are similar to primitive types in Java (like Integer/String/Double etc.)
  • Complex types – these are container types wherein they wrap other types, including nesting of types, but will have some basic type at final level of nesting (like list of long or map of list of strings)

When you put the data in table, using APIs, you will have to provide the value as respective Java type. Similarly, when you perform scan/get operation the Java object of respective type is provided.

Basic Types:

Below table shows various basic types supported when using MTable. These are provided by class BasicTypes.

Type in Ampool Table Respective Java Type
BasicTypes.INT Integer
BasicTypes.STRING String
BasicTypes.LONG Long
BasicTypes.SHORT Short
BasicTypes.BYTE Byte
BasicTypes.BOOLEAN Boolean
BasicTypes.DOUBLE Double
BasicTypes.FLOAT Float
BasicTypes.DATE java.sql.Date
BasicTypes.TIMESTAMP java.sql.Timestamp
BasicTypes.BIG_DECIMAL BigDecimal
BasicTypes.CHARS Char[]

Complex Types:

Below table shows various complex types supported by MTable. These are container types and these are used to wrap other types, including themselves or the basic types.

Type used in Ampool Table Respective Java Type
array List or T[]
map Map
struct Object[]

The LIST and MAP types are similar to respective Java types. Whereas STRUCT is similar to C-language structures which can contain multiple columns with their respective types. These are expected in the same order that was provided at the time of creation. When specifying complex types the contained types must be enclosed within diamond brackets (i.e. < and >) and in case multiple columns are to be provided (for example STRUCT) these should be separated by comma (,).

Below are few examples how you can specify the complex types:

* array<INT>
* map<STRING,array<DOUBLE>>
* struct<C1:STRING,C2:DATE,C3:DOUBLE>

Note

When specifying column names you should use only alpha-numeric characters.

MTable Examples w/ Column Types

Example 1: Basic Objects

Following is a step-by-step demonstration of how to use types with MTable APIs. It assumed that you already have client cache created and the client is part of the required pool.

1. Create table with desired types

You need to create table descriptor with the required types. The API addColumn expects two arguments, as String: column-name and column-type

MClientCache cache = getClientCache(); /** assumed that you are getting the correct instance of client-cache **/

final String[] columnNames = new String[] { "NAME", "ID", "AGE", "SALARY", "DEPT", "DOJ"};
final String[] columnTypes = new String[] { "STRING", "LONG", "INT", "DOUBLE", "STRING", "DATE"};
final String tableName = "EmployeeTable";
final MTableDescriptor td = new MTableDescriptor();
for (int i = 0; i < columnNames.length; i++) {
  td.addColumn(columnNames[i], columnTypes[i]);
}
cache.getAdmin().createTable(tableName, td);

The createTable API accepts two arguments: a table name and a table-descriptor that has column details (i.e. column-name and column-type).

2. Add data entries to the table

Once the table is created you can create a row with respective values and put/store that into MTable by associating a row-key with it.

/** the sample data with five columns with types:
  *  STRING, LONG, INT, DOUBLE, STRING, DATE
  */
final Object[][] sampleData = new Object[][]{
  {"Name_1", 1L, 11, 11.111, "ABC", Date.valueOf("2016-01-01")},
  {"Name_2", 2L, 22, 22.222, "ABC", Date.valueOf("2016-02-02")},
  {"Name_3", 3L, 33, 33.333, "ABC", Date.valueOf("2016-03-03")},
  {"Name_4", 4L, 44, 44.444, "ABC", Date.valueOf("2016-04-04")},
  {"Name_5", 5L, 55, 55.555, "ABC", Date.valueOf("2016-05-05")},
};

MPut mPut;
for (int i = 0; i < sampleData.length; i++) {
 mPut = new MPut("rowKey_" + i);
 for (int j = 0; j < sampleData[i].length; j++) {
 mPut.addColumn(columnNames[j], sampleData[i][j]);
 }
 mTable.put(mPut);
}

3. Test (retrieve) the values from the table

After you have put the necessary data into MTable, you can retrieve the data using MGet API (using the respective row-key).

MGet mGet;
MResult mResult;
List<MCell> cells;
for (int i = 0; i < sampleData.length; i++) {
  mGet = new MGet("rowKey_" + i);
  /** additionally you can provided the selected columns, if you want **/
  /** mGet.addColumn(columnNames[3].getBytes()); **/

  mResult = mTable.get(mGet);
  cells = mResult.getCells();
  for (int j = 0; j < cells.size(); j++) {
    System.out.print("| " + cells.get(i).getColumnValue() + "\t");
  }
  System.out.println();
}

The get API returns you a result object i.e. row, which contains a list of cells. These are in the same order as you had provided during create. It is also possible to get only selected columns when doing get by specifying the columns that you want to retrieve.

Example 2: Complex Types

Here is another example demonstrating how to use complex type like STRUCT. The has structure similar to a table i.e. it has distinct columns and respective values. For example, in previous example we created a table with six columns having respective types. Effectively we can represent same data using a single column with STRUCT type that interprets same structure.

For basic types only name is required to be provided but for complex types name as well as the contained types (along with respective name, in case of STRUCT) needs to be provided. This can be done by enclosing the information of the contained types within diamond brackets (i.e. < >).

For example schema for the above table can be constructed as a single column using STRUCT as: struct<NAME:STRING,ID:LONG,AGE:INT,SALARY:DOUBLE,DEPT:STRING,DOJ:DATE> Once the type is constructed from the available data, the table can be created and then put/get APIs can be used to perform respective operations. Below is a sample code for the same.

final String structTable = "struct_table";
final String structColumn = "struct_column";
final String structType = "struct<NAME:STRING,ID:LONG,AGE:INT,SALARY:DOUBLE,DEPT:STRING,DOJ:DATE>";
MTableDescriptor td = new MTableDescriptor();
td.addColumn(structColumn, structType);
final MTable sTable = cache.getAdmin().createTable(structTable, td);

for (int i = 0; i < sampleData.length; i++) {
 mPut = new MPut("rowKey_" + i);
 mPut.addColumn(structColumn, sampleData[i]);
 sTable.put(mPut);
}

System.out.println("Retrieving struct_column:");
Object[] values;
for (int i = 0; i < sampleData.length; i++) {
 mGet = new MGet("rowKey_" + i);
 values = (Object[])sTable.get(mGet).getCells().get(0).getColumnValue();
 for (int j = 0; j < values.length; j++) {
 System.out.printf("| %6s ", values[j]);
 }
 System.out.println("|");
}