Google Cloud Bigtable emulator seems to drop column families - java

I am trying to create a table with a single column family (targeting the Google Cloud Bigtable emulator using Java client library 0.9.1).
private void setupTable() throws IOException {
TableName name = TableName.valueOf("EndOfDayPriceUnadjusted");
try(Connection connection = BigtableConfiguration.connect(hbaseConf)){
HTableDescriptor descriptor = new HTableDescriptor(name);
descriptor.addFamily(new HColumnDescriptor("EOD"));
connection.getAdmin().createTable(descriptor);
// calling HTableDescriptor desc = connection.getAdmin().getTableDescriptor(name); yields the same result
Table t = connection.getTable(name);
if(t.getTableDescriptor().getColumnFamilies().length == 0)
log.error("no column families.");
else
log.info("table with column family created.");
}
}
My problem is that after creating the table, the retrieved descriptor never contains the EOD family; therefore, any calls to store data in that column family fails.
Am I missing something or is it a limitation of the emulator?

An emulator-specific workaround you can use until the bug is fixed is to add the column family after creating the table:
connector.getAdmin().addColumn(
descriptor.getTableName(), new HColumnDescriptor("EOD"));

Related

Is possible to add column(s) to an existing table using the google-cloud-java SDK

Is possible to add column(s) to an existing table using the google-cloud-java SDK ?
BigQuery interface does have a update method, but it seems only able to table's metadata
Yup, it sure is. Use the update method and provide the new schema. You need to provide the entire schema i.e. the old and new column(s). null will be inserted for the new column(s) values.
This example will add column_2 to the existing table which already has column_1:
String datasetName = "test";
String tableName = "foo";
Table oldTable = bigQuery.getTable(datasetName, tableName);
Field col1 = Field.of("column_1", Field.Type.string());
Field col2 = Field.of("column_2", Field.Type.string());
Schema schema = Schema.of(col1, col2);
TableInfo tableInfo = oldTable.toBuilder().setDefinition(StandardTableDefinition.of(schema)).build();
bigQuery.update(tableInfo);
http://googlecloudplatform.github.io/google-cloud-java/0.9.3/apidocs/?com/google/cloud/bigquery/package-summary.html

UpdateTableSpec on dynamoDB table is not working

Can any one let me know whether UpdateTableSpec can only update KeySchema attributes and is there any way to update/modify a table with non-keyschema attributes ? My scenario is : I created a table with composite key comprising of a primary ( #id attribute) and range key ( #Name attribute). Now I want to add a third attribute, Gender, which is not a part of keyschema. Is it possible ?
I am updating my DynamoDB table using the following code but it does not add the Gender attribute, although it successfully updates the provisioned attribute:
static void updateTable() {
System.out.println("Updating the table with new attributes ...");
Table table = dynamoDB.getTable(tableName);
UpdateTableSpec updateTableSpec = new UpdateTableSpec();
List<AttributeDefinition> attributeDefinitionList = updateTableSpec.getAttributeDefinitions();
if (null == attributeDefinitionList) {
attributeDefinitionList = new ArrayList<AttributeDefinition>();
}
attributeDefinitionList.add(new AttributeDefinition()
.withAttributeName("Gender")
.withAttributeType("S"));
updateTableSpec.withAttributeDefinitions(attributeDefinitionList)
.withProvisionedThroughput(new ProvisionedThroughput()
.withReadCapacityUnits(6L)
.withWriteCapacityUnits(7L));;
table.updateTable(updateTableSpec);
try {
table.waitForActive();
System.out.println("Table updated succesfully");
} catch (final Exception ex) {
System.out.println("Exception occurred while updating the table");
}
}
You cannot update key schema for a DynamoDB table. Update Table API can be used only for (from the doc):
Modify the provisioned throughput settings of the table.
Enable or disable Streams on the table.
Remove a global secondary index from the table.
Create a new global secondary index on the table. Once the index begins backfilling, you can use UpdateTable to perform other operations.
Your best option, I think, is to migrate to a new table with the desired new key schema. You can see other options here.

Getting column metadata from jdbc/postgresql for newly created table

I'm trying to get the column list from newly created table(it is created in the java code).
The thing is that I do not get the columns.
The code works for tables that are already in the database, but if i create a new one and try to get the column info immediately it does not find any...
Update:
Here is full code that I used for testing:
#Test
public void testtest() throws Exception {
try (Connection conn = dataSource.getConnection()) {
String tableName = "Table_" + UUID.randomUUID().toString().replace("-", "");
try (Statement statement = conn.createStatement()) {
statement.executeUpdate(String.format("create table %s (id int primary key,name varchar(30));", tableName));
}
DatabaseMetaData metaData = conn.getMetaData();
try (ResultSet rs = metaData.getColumns(null, null, tableName, null)) {
int colsFound = 0;
while (rs.next()) {
colsFound++;
}
System.out.println(String.format("Found %s cols.", colsFound));
}
System.out.println(String.format("Autocommit is set to %s.", conn.getAutoCommit()));
}
}
The and the output:
Found 0 cols.
Autocommit is set to true.
The problem is with the case of your tablename:
String tableName = "Table_"
As that is an unquoted identifier (a good thing) the name is converted to lowercase when Postgres stores its name in the system catalog.
The DatabaseMetaData API calls are case sensitive ( "Table_" != "table_"), so you need to pass the lowercase tablename:
ResultSet rs = metaData.getColumns(null, null, tableName.toLowerCase(), null))
More details on how identifiers are using are in the manual: http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
I have made simple test and it seems to work. I can create new table and show its columns using PostgreSQL JDBC (I use Jython):
conn = db.createStatement()
conn.execute("CREATE TABLE new_table (id SERIAL, txt VARCHAR(200))")
db_meta_data = db.getMetaData()
for tbl_name in ('date_test', 'new_table'):
print('\n-- %s --' % (tbl_name))
rs = db_meta_data.getColumns(None, None, tbl_name, None)
while (rs.next()):
print('%s:%s' % (rs.getString(3), rs.getString(4)))
conn.close()
This code shows columns for both already existing table: date_test and for just created new_table. I also added some code to close connection after CREATE TABLE but my results are always the same and correct.
Maybe it is problem with your JDBC driver. I use driver from postgresql-9.3-1100.jdbc41.jar.
It may be also problem with user permissions. Do you use the same user for both creating table and getting metadata? Is new table visible in psql, pgAdmin or other tool?
Other reason is that PostgreSQL uses transactions also for schema changes. So if you disabled default autocommit and closed connection your schema changes will be lost. Do you use db.setAutoCommit(false)?
You can also query PostgreSQL schema directly:
SELECT DISTINCT table_name, column_name
FROM information_schema.columns
WHERE table_schema='public'
AND table_name = 'new_table'
ORDER BY 1, 2
Strangely giving passing table name in lower case to getColumns method does work...thanks for the query MichaƂ Niklas it got me on the right track.

Getting foreign key and refering table name of particular database table from metadata DatabaseMetaData using JAVA class

I am writing java class to get all connection database objects(tables). I have used
rs = meta.getExportedKeys(conn.getCatalog(), null, "account_adjustment");
while (rs.next()) {
String fkTableName = rs.getString("FKTABLE_NAME");
String fkColumnName = rs.getString("FKCOLUMN_NAME");
int fkSequence = rs.getInt("KEY_SEQ");
}
which is giving parent table and it's column linked this asked table(account_adjustment)
and also I tried
rs1 = meta.getImportedKeys(conn.getCatalog(), null, "account_adjustment");
while (rs1.next()) {
String fkTableName = rs1.getString("FKTABLE_NAME");
String fkColumnName = rs1.getString("FKCOLUMN_NAME");
int fkSequence = rs1.getInt("KEY_SEQ");
}
which is giving current table(account_adjustment) table and it's foreign key column name
but I want table name with which this foreign key is linked
I have got solution bt in other way not using java,, instead of getting values using java i executed query to 'information_schema' (which is there by default in MySQL) database and 'REFERENTIAL_CONSTRAINTS' table to get all reference of respective tables of required database

Why does getGeneratedKeys() return "GENERATED_KEY" as column name?

I'm playing with the JDBC/MySQL 5.1. I created an insert query to insert some data into a table and want to return the generated key from the newly created row. However, when I go to reference the column by "id" which is my PK and auto-increment column.
PreparedStatement ps = St0rm.getInstance().getDatabase("main")
.prepare("INSERT INTO quests (name,minlevel,start_npc,end_npc) VALUES(?,?,?,?)", true); // creates a prepared statement with flag RETURN_GENERATED_KEYS
// ...
int affected = ps.executeUpdate();
ResultSet keys = ps.getGeneratedKeys();
if (affected > 0 && keys.next()) {
St0rm.getInstance().getLogger().warning(String.format("ID Column Name: %s", keys.getMetaData().getColumnName(1))); // says the column name is: GENERATED_KEY
q = new Quest(keys.getInt(1)); // column index from the generated key, no error thrown.
q = new Quest(keys.getInt("id")); // actual column name, line throws a SQLException
// ...
}
So, my question: Why does ResultSet.getGeneratedKeys use GENERATED_KEY as the column name?
You shouldn't retrieve these columns by name. Only by index, since
there can only ever be one column with MySQL and auto_increments that
returns value(s) that can be exposed by Statement.getGeneratedKeys().
Currently the MySQL server doesn't return information directly that
would make the ability to retrieve these columns by name in an
efficient manner possible, which is why I'm marking this as "to be
fixed later", since we can, once the server returns the information in
a way that the driver can use.
From here (in 2006!).

Categories