package org.simpleflatmapper.jdbc.impl; import org.simpleflatmapper.jdbc.Crud; import org.simpleflatmapper.jdbc.JdbcMapperFactory; import org.simpleflatmapper.jdbc.PreparedStatementMapperBuilder; import org.simpleflatmapper.jdbc.QueryPreparer; import org.simpleflatmapper.jdbc.named.NamedSqlQuery; import org.simpleflatmapper.reflect.meta.ClassMeta; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class PostgresqlCrudFactory { public static <T, K> Crud<T, K> newInstance(ClassMeta<T> target, ClassMeta<K> keyTarget, CrudMeta crudMeta, JdbcMapperFactory jdbcMapperFactory, DefaultCrud<T, K> defaultCrud) throws SQLException { return new MultiRowsBatchInsertCrud<T, K>( defaultCrud, buildBatchInsert(target, crudMeta, jdbcMapperFactory, false), buildBatchInsert(target, crudMeta, jdbcMapperFactory, true)); } private static <T, K> BatchQueryExecutor<T> buildBatchInsert( ClassMeta<T> target, CrudMeta crudMeta, JdbcMapperFactory jdbcMapperFactory, boolean onDuplicateKeyUpdate) throws SQLException { List<String> generatedKeys = new ArrayList<String>(); List<String> insertColumns = new ArrayList<String>(); List<String> insertColumnExpressions = new ArrayList<String>(); List<String> updateColumns = new ArrayList<String>(); List<String> keys = new ArrayList<String>(); PreparedStatementMapperBuilder<T> statementMapperBuilder = jdbcMapperFactory.<T>from(target); for(ColumnMeta cm : crudMeta.getColumnMetas()) { String columnName = cm.getColumn(); if (cm.isGenerated()) { generatedKeys.add(columnName); } if (cm.isInsertable()) { insertColumns.add(columnName); insertColumnExpressions.add(cm.getInsertExpression()); if (!cm.isGenerated()) { statementMapperBuilder.addColumn(columnName); } } if (!cm.isKey()) { updateColumns.add(columnName); } else { keys.add(columnName); } } PostgresqlBatchInsertQueryExecutor<T> queryExecutor = new PostgresqlBatchInsertQueryExecutor<T>( crudMeta.getTable(), insertColumns.toArray(new String[0]), insertColumnExpressions.toArray(new String[0]), onDuplicateKeyUpdate ? updateColumns.toArray(new String[0]) : null, generatedKeys.toArray(new String[0]), keys.toArray(new String[0]), statementMapperBuilder.buildIndexFieldMappers()); return queryExecutor; } public static <T, K> QueryPreparer<T> buildUpsert(ClassMeta<T> target, CrudMeta crudMeta, JdbcMapperFactory jdbcMapperFactory) { List<String> generatedKeys = new ArrayList<String>(); StringBuilder sb = new StringBuilder(); sb.append("INSERT INTO "); sb.append(crudMeta.getTable()).append("("); boolean first = true; for(ColumnMeta cm : crudMeta.getColumnMetas()) { if (cm.isGenerated()) { generatedKeys.add(cm.getColumn()); } if (cm.isInsertable()) { if (!first) { sb.append(", "); } sb.append(cm.getColumn()); first = false; } } sb.append(") VALUES("); first = true; for(ColumnMeta cm : crudMeta.getColumnMetas()) { if (cm.isInsertable()) { if (!first) { sb.append(", "); } sb.append(cm.getInsertExpression()); first = false; } } sb.append(") ON CONFLICT ("); first = true; for(ColumnMeta cm : crudMeta.getColumnMetas()) { if (cm.isKey()) { if (!first) { sb.append(", "); } sb.append(cm.getColumn()); first = false; } } sb.append(") DO UPDATE SET "); first = true; for(ColumnMeta cm : crudMeta.getColumnMetas()) { if (!cm.isKey()) { if (!first) { sb.append(", "); } sb.append(cm.getColumn()); sb.append(" = EXCLUDED.").append(cm.getColumn()); first = false; } } return jdbcMapperFactory.<T>from(target).to(NamedSqlQuery.parse(sb), generatedKeys.toArray(new String[0])); } }