use of com.google.cloud.spanner.Type.StructField in project java-spanner-jdbc by googleapis.
the class JdbcResultSetMetaDataTest method getFooTestResultSet.
private JdbcResultSet getFooTestResultSet(Statement statement) {
List<Struct> rows = new ArrayList<>(4);
for (int row = 1; row <= 4; row++) {
Struct.Builder builder = Struct.newBuilder();
for (TestColumn col : TEST_COLUMNS) {
builder.set(col.name).to(getDefaultValue(col.type, row));
}
rows.add(builder.build());
}
StructField[] fields = new StructField[TEST_COLUMNS.size()];
int index = 0;
for (TestColumn col : TEST_COLUMNS) {
fields[index] = StructField.of(col.name, col.type);
index++;
}
ResultSet rs = ResultSets.forRows(Type.struct(fields), rows);
return JdbcResultSet.of(statement, rs);
}
use of com.google.cloud.spanner.Type.StructField in project jans by JanssenProject.
the class SpannerFilterConverter method buildVariableExpression.
private Expression buildVariableExpression(TableMapping tableMapping, String attributeName, Object attribyteValue, Map<String, ValueWithStructField> queryParameters) throws SearchException {
StructField structField = getStructField(tableMapping, attributeName);
String usedAttributeName = attributeName;
int idx = 0;
while (queryParameters.containsKey(usedAttributeName) && (idx < 100)) {
usedAttributeName = attributeName + Integer.toString(idx++);
}
queryParameters.put(usedAttributeName, new ValueWithStructField(attribyteValue, structField));
return new UserVariable(usedAttributeName);
}
use of com.google.cloud.spanner.Type.StructField in project jans by JanssenProject.
the class SpannerOperationServiceImpl method getAttributeDataList.
private List<AttributeData> getAttributeDataList(String objectClass, ResultSet resultSet, boolean skipDn) throws EntryConvertationException {
try {
if ((resultSet == null)) {
return null;
}
if (!resultSet.next()) {
return null;
}
List<AttributeData> result = new ArrayList<AttributeData>();
// TODO: Include child table columns
Set<String> nullableColumns = connectionProvider.getTableNullableColumns(objectClass);
List<StructField> structFields = resultSet.getType().getStructFields();
int columnsCount = resultSet.getColumnCount();
for (int i = 0; i < columnsCount; i++) {
StructField structField = structFields.get(i);
String attributeName = structField.getName();
Code columnTypeCode = structField.getType().getCode();
boolean isNullable = nullableColumns.contains(attributeName.toLowerCase());
if (SpannerOperationService.DOC_ID.equalsIgnoreCase(attributeName) || SpannerOperationService.ID.equalsIgnoreCase(attributeName)) {
// Skip internal attributes
continue;
}
if (skipDn && SpannerOperationService.DN.equalsIgnoreCase(attributeName)) {
// Skip DN attribute
continue;
}
Boolean multiValued = Boolean.FALSE;
Object[] attributeValueObjects;
if (resultSet.isNull(i)) {
attributeValueObjects = NO_OBJECTS;
if (isNullable) {
// Ignore columns with default NULL values
continue;
}
} else {
if (Code.ARRAY == columnTypeCode) {
attributeValueObjects = convertDbArrayToValue(resultSet, structField.getType().getArrayElementType(), i, attributeName);
multiValued = Boolean.TRUE;
} else if (Code.BOOL == columnTypeCode) {
attributeValueObjects = new Object[] { resultSet.getBoolean(i) };
} else if (Code.DATE == columnTypeCode) {
attributeValueObjects = new Object[] { com.google.cloud.Date.toJavaUtilDate(resultSet.getDate(i)) };
} else if (Code.TIMESTAMP == columnTypeCode) {
attributeValueObjects = new Object[] { resultSet.getTimestamp(i).toDate() };
} else if (Code.INT64 == columnTypeCode) {
attributeValueObjects = new Object[] { resultSet.getLong(i) };
} else if (Code.NUMERIC == columnTypeCode) {
attributeValueObjects = new Object[] { resultSet.getBigDecimal(i).longValue() };
} else if (Code.STRING == columnTypeCode) {
Object value = resultSet.getString(i);
try {
value = com.google.cloud.Timestamp.parseTimestamp(value.toString());
} catch (Exception ex) {
}
attributeValueObjects = new Object[] { value };
} else {
throw new EntryConvertationException(String.format("Column with name '%s' does not contain unsupported type '%s'", attributeName, columnTypeCode));
}
}
unescapeValues(attributeValueObjects);
AttributeData tmpAttribute = new AttributeData(attributeName, attributeValueObjects, multiValued);
if (multiValued != null) {
tmpAttribute.setMultiValued(multiValued);
}
result.add(tmpAttribute);
}
return result;
} catch (SpannerException ex) {
throw new EntryConvertationException("Failed to convert entry!", ex);
}
}
use of com.google.cloud.spanner.Type.StructField in project jans by JanssenProject.
the class SpannerOperationServiceImpl method updateEntryImpl.
private boolean updateEntryImpl(TableMapping tableMapping, String key, List<AttributeDataModification> mods) throws PersistenceException {
try {
MessageDigest messageDigest = getMessageDigestInstance();
Map<String, StructField> columTypes = tableMapping.getColumTypes();
WriteBuilder mutationBuilder = Mutation.newInsertOrUpdateBuilder(tableMapping.getTableName()).set(SpannerOperationService.DOC_ID).to(key);
List<Mutation> mutations = new LinkedList<>();
for (AttributeDataModification attributeMod : mods) {
AttributeData attribute = attributeMod.getAttribute();
AttributeModificationType type = attributeMod.getModificationType();
String attributeName = attribute.getName();
StructField attributeType = columTypes.get(attributeName.toLowerCase());
// If column not inside table we should check if there is child table
if (attributeType == null) {
TableMapping childTableMapping = connectionProvider.getChildTableMappingByKey(key, tableMapping, attributeName);
if (childTableMapping == null) {
throw new PersistenceException(String.format("Failed to update entry. Column '%s' is undefined", attributeName));
}
Map<String, StructField> childColumTypes = childTableMapping.getColumTypes();
StructField childAttributeType = childColumTypes.get(attributeName.toLowerCase());
// Build Mutation for child table
Map<String, Object> oldValues = null;
if ((attributeMod.getOldAttribute() != null) && (attributeMod.getOldAttribute().getValues() != null)) {
oldValues = new HashMap<>();
for (Object oldValue : attributeMod.getOldAttribute().getValues()) {
String dictDocId = getStringUniqueKey(messageDigest, oldValue);
oldValues.put(dictDocId, oldValue);
}
}
if ((AttributeModificationType.ADD == type) || (AttributeModificationType.FORCE_UPDATE == type) || (AttributeModificationType.REPLACE == type)) {
for (Object value : attribute.getValues()) {
WriteBuilder childMutationBuilder = Mutation.newInsertOrUpdateBuilder(childTableMapping.getTableName());
String dictDocId = getStringUniqueKey(messageDigest, value);
childMutationBuilder.set(SpannerOperationService.DOC_ID).to(key).set(SpannerOperationService.DICT_DOC_ID).to(dictDocId);
setMutationBuilderValue(childMutationBuilder, childAttributeType, value);
mutations.add(childMutationBuilder.build());
if (oldValues != null) {
oldValues.remove(dictDocId);
}
}
} else if (AttributeModificationType.REMOVE == type) {
// Build Mutation for child table
com.google.cloud.spanner.KeySet.Builder keySetBuilder = KeySet.newBuilder();
for (Object value : attribute.getValues()) {
String dictDocId = getStringUniqueKey(messageDigest, value);
keySetBuilder.addKey(Key.of(key, dictDocId));
}
Mutation childMutation = Mutation.delete(childTableMapping.getTableName(), keySetBuilder.build());
mutations.add(childMutation);
} else {
throw new UnsupportedOperationException("Operation type '" + type + "' is not implemented");
}
if ((oldValues != null) && (oldValues.size() > 0)) {
com.google.cloud.spanner.KeySet.Builder keySetBuilder = KeySet.newBuilder();
for (String removeDictDocId : oldValues.keySet()) {
keySetBuilder.addKey(Key.of(key, removeDictDocId));
}
Mutation childMutation = Mutation.delete(childTableMapping.getTableName(), keySetBuilder.build());
mutations.add(childMutation);
}
} else {
if ((AttributeModificationType.ADD == type) || (AttributeModificationType.FORCE_UPDATE == type) || (AttributeModificationType.REPLACE == type)) {
setMutationBuilderValue(mutationBuilder, attributeType, attribute.getValues());
} else if (AttributeModificationType.REMOVE == type) {
removeMutationBuilderValue(mutationBuilder, attribute, attributeType);
} else {
throw new UnsupportedOperationException("Operation type '" + type + "' is not implemented");
}
}
}
mutations.add(0, mutationBuilder.build());
databaseClient.write(mutations);
return true;
} catch (SpannerException | IllegalStateException ex) {
throw new PersistenceException("Failed to update entry", ex);
}
}
use of com.google.cloud.spanner.Type.StructField in project jans by JanssenProject.
the class SpannerConnectionProvider method loadTableMetaData.
private void loadTableMetaData() {
LOG.info("Scanning DB metadata...");
long takes = System.currentTimeMillis();
try (ResultSet resultSet = executeQuery(QUERY_PARENT_TABLE)) {
if (resultSet.next()) {
int tableNameIdx = resultSet.getColumnIndex("TABLE_NAME");
int parentTableNameIdx = resultSet.getColumnIndex("PARENT_TABLE_NAME");
do {
String parentTableName = resultSet.getString(parentTableNameIdx);
String tableName = resultSet.getString(tableNameIdx);
Set<String> childAttributes;
if (tableChildAttributesMap.containsKey(parentTableName)) {
childAttributes = tableChildAttributesMap.get(parentTableName);
} else {
childAttributes = new HashSet<>();
tableChildAttributesMap.put(parentTableName, childAttributes);
}
if (tableName.startsWith(parentTableName + "_")) {
tableName = tableName.substring(parentTableName.length() + 1);
}
childAttributes.add(tableName);
} while (resultSet.next());
}
} catch (SpannerException ex) {
throw new ConnectionException("Failed to get database metadata", ex);
}
LOG.debug("Build child attributes map: '{}'.", tableChildAttributesMap);
HashMap<String, Type> typeMap = buildSpannerTypesMap();
try (ResultSet resultSet = executeQuery(QUERY_TABLE_SCHEMA)) {
if (resultSet.next()) {
int tableNameIdx = resultSet.getColumnIndex("TABLE_NAME");
int columnNameIdx = resultSet.getColumnIndex("COLUMN_NAME");
int spannerTypeIdx = resultSet.getColumnIndex("SPANNER_TYPE");
int isNullableIdx = resultSet.getColumnIndex("IS_NULLABLE");
do {
String tableName = resultSet.getString(tableNameIdx);
String columnName = resultSet.getString(columnNameIdx);
String spannerType = resultSet.getString(spannerTypeIdx);
String isNullable = resultSet.getString(isNullableIdx);
// Load table schema
Map<String, StructField> tableColumns;
if (tableColumnsMap.containsKey(tableName)) {
tableColumns = tableColumnsMap.get(tableName);
} else {
tableColumns = new HashMap<>();
tableColumnsMap.put(tableName, tableColumns);
}
String comparebleType = toComparableType(spannerType);
Type type = typeMap.get(comparebleType);
if (type == null) {
throw new ConnectionException(String.format("Failed to parse SPANNER_TYPE: '%s'", spannerType));
}
tableColumns.put(columnName.toLowerCase(), StructField.of(columnName, type));
// Check if column nullable
Set<String> nullableColumns;
if (tableNullableColumnsSet.containsKey(tableName)) {
nullableColumns = tableNullableColumnsSet.get(tableName);
} else {
nullableColumns = new HashSet<>();
tableNullableColumnsSet.put(tableName, nullableColumns);
}
boolean nullable = "yes".equalsIgnoreCase(isNullable);
if (nullable) {
nullableColumns.add(columnName.toLowerCase());
}
} while (resultSet.next());
}
} catch (SpannerException ex) {
throw new ConnectionException("Failed to get database metadata", ex);
}
LOG.debug("Build table columns map: '{}'.", tableColumnsMap);
takes = System.currentTimeMillis() - takes;
LOG.info("Metadata scan finisehd in {} milliseconds", takes);
}
Aggregations