in src/main/java/org/opensearch/performanceanalyzer/rca/persistence/SQLitePersistor.java [692:798]
private <T> int writeImplInner(T obj)
throws IllegalStateException, IllegalAccessException, InvocationTargetException,
SQLException, NoSuchMethodException {
Class<?> clz = obj.getClass();
String tableName = getTableNameFromClassName(clz);
Table<Record> table = DSL.table(tableName);
// If there exists a table with the same name as the SimpleName of this class, make sure
// that the persisted class is same as this.
// This is to avoid cases of trying to persist classes from two different packages with the
// same name.
if (jooqTableColumns.containsKey(tableName)) {
// There can be a case where two distinct classes with the same SimpleName, might want
// to persist themselves. In this case, we should keep things simple and throw an error.
Class<?> alreadyStoredTableClass = tableNameToJavaClassMap.get(tableName);
Objects.requireNonNull(
alreadyStoredTableClass,
"A table exists with this name but the table is not mapped to a Java class.");
if (alreadyStoredTableClass != clz) {
throw new IllegalStateException(
"There is already a table in the Database with the same name. It belongs to the class: '"
+ alreadyStoredTableClass
+ "'. Please consider re-naming your classes.");
}
Objects.requireNonNull(
fieldGetterSetterPairsMap.get(clz),
"Because the class is already persisted once, we should have the "
+ "mapping for field to their corresponding getter and setters.");
} else {
createFieldRegistry(clz);
}
Map<java.lang.reflect.Field, GetterSetterPairs> fieldToGetterSetterMap =
fieldGetterSetterPairsMap.get(clz);
List<Field<?>> fields = new ArrayList<>();
List<Object> values = new ArrayList<>();
for (Map.Entry<java.lang.reflect.Field, GetterSetterPairs> entry :
fieldToGetterSetterMap.entrySet()) {
Method getter = entry.getValue().getter;
java.lang.reflect.Field classField = entry.getKey();
String columnName = classField.getName();
Class<?> retType = getter.getReturnType();
if (classField.isAnnotationPresent(RefColumn.class)) {
columnName = NESTED_OBJECT_COLUMN_PREFIX + columnName;
if (Collection.class.isAssignableFrom(retType)) {
ColumnValuePair columnValuePair =
writeCollectionReferenceColumn(classField, getter, obj);
fields.add(columnValuePair.field);
values.add(columnValuePair.value);
} else {
// This is a user-defined class Type
int id = writeImplInner(retType.cast(getter.invoke(obj)));
// Although the ID is long, we are persisting it as string because if there are
// multiple rows in the child table, that refer to
// the parent table row, then, the parent table should have a list of them. IN
// which case the value stored in the column will be
// of the form: [id1, id2, ..].
fields.add(DSL.field(DSL.name(columnName), Integer.class));
values.add(id);
}
} else if (retType.isPrimitive()) {
fields.add(DSL.field(DSL.name(columnName), retType));
values.add(getter.invoke(obj));
} else if (retType == String.class) {
fields.add(DSL.field(DSL.name(columnName), String.class));
values.add(getter.invoke(obj));
}
}
if (fields.size() == 0) {
StringBuilder sb = new StringBuilder();
sb.append("Class ")
.append(clz.getSimpleName())
.append(" was asked to be persisted but there are no fields with annotations: ")
.append(ValueColumn.class.getSimpleName())
.append(" or ")
.append(RefColumn.class.getSimpleName());
throw new IllegalStateException(sb.toString());
}
// If table does not exist, try to create one.
if (!jooqTableColumns.containsKey(tableName)) {
createTable(tableName, fields);
tableNameToJavaClassMap.put(tableName, obj.getClass());
}
try {
int ret = create.insertInto(table).columns(fields).values(values).execute();
} catch (Exception e) {
LOG.error("Inserting row '{}' into table '{}' failed", values, tableName, e);
throw new SQLException(e);
}
int lastRowId = -1;
String sqlQuery = "SELECT " + LAST_INSERT_ROWID;
try {
lastRowId = create.fetch(sqlQuery).get(0).get(LAST_INSERT_ROWID, Integer.class);
} catch (Exception e) {
LOG.error("Failed to insert into the table {}", table, e);
throw new SQLException(e);
}
LOG.debug("most recently inserted primary key = {}", lastRowId);
return lastRowId;
}