use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.
the class PgUtil method collection.
private static <T, C> C collection(Class<T> clazz, Class<C> collectionClazz, RowSet<Row> resultSet, int offset, int limit) throws ReflectiveOperationException, IOException {
int totalRecords = 0;
int resultSize = resultSet.size();
List<T> recordList = new ArrayList<>(resultSize);
RowIterator<Row> iterator = resultSet.iterator();
while (iterator.hasNext()) {
Row row = iterator.next();
String jsonb = row.getValue(JSON_COLUMN).toString();
recordList.add(OBJECT_MAPPER.readValue(jsonb, clazz));
totalRecords = row.getInteger(PostgresClient.COUNT_FIELD);
}
totalRecords = PostgresClient.getTotalRecords(resultSize, totalRecords, offset, limit);
return collection(collectionClazz, recordList, totalRecords);
}
use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.
the class PgUtil method postSync.
/**
* Post a list of T entities to the database. Fail all if any of them fails.
* @param table database table to store into
* @param entities the records to store
* @param maxEntities fail with HTTP 413 if entities.size() > maxEntities to avoid out of memory;
* suggested value is from 100 ... 10000.
* @param upsert true to update records with the same id, false to fail all entities if one has an existing id
* @param okapiHeaders http headers provided by okapi
* @param vertxContext the current context
* @param responseClass the ResponseDelegate class created from the RAML file with these methods:
* respond201(), respond409WithTextPlain(Object), respond413WithTextPlain(Object), respond500WithTextPlain(Object).
* @return future where to return the result created by responseClass
*/
public static <T> Future<Response> postSync(String table, List<T> entities, int maxEntities, boolean upsert, Map<String, String> okapiHeaders, Context vertxContext, Class<? extends ResponseDelegate> responseClass) {
final Method respond500;
try {
respond500 = responseClass.getMethod(RESPOND_500_WITH_TEXT_PLAIN, Object.class);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return response(e.getMessage(), null, null);
}
try {
Method respond201 = responseClass.getMethod(RESPOND_201);
Method respond409 = getRespond409(responseClass);
Method respond413 = responseClass.getMethod(RESPOND_413_WITH_TEXT_PLAIN, Object.class);
if (entities != null && entities.size() > maxEntities) {
String message = "Expected a maximum of " + maxEntities + " records to prevent out of memory but got " + entities.size();
return response(message, respond413, respond500);
}
// RestVerticle populates a single record only, not an array of records
Promise<Response> promise = Promise.promise();
MetadataUtil.populateMetadata(entities, okapiHeaders);
PostgresClient postgresClient = postgresClient(vertxContext, okapiHeaders);
Handler<AsyncResult<RowSet<Row>>> replyHandler = result -> {
if (result.failed()) {
if (PgExceptionUtil.isVersionConflict(result.cause())) {
Method method = respond409 == null ? respond500 : respond409;
response(result.cause().getMessage(), method, respond500).onComplete(promise);
} else {
response(table, /* id */
"", result.cause(), responseClass, respond500, respond500).onComplete(promise);
}
}
response(respond201, respond500).onComplete(promise);
};
if (upsert) {
postgresClient.upsertBatch(table, entities, replyHandler);
} else {
postgresClient.saveBatch(table, entities, replyHandler);
}
return promise.future();
} catch (Exception e) {
logger.error(e.getMessage(), e);
return response(e.getMessage(), respond500, respond500);
}
}
use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.
the class PostgresClient method executeGetQuery.
private <T> void executeGetQuery(PgConnection connection, QueryHelper queryHelper, ResultInfo resultInfo, Class<T> clazz, Handler<AsyncResult<PostgresClientStreamResult<T>>> replyHandler, Transaction transaction) {
connection.prepare(queryHelper.selectQuery, prepareRes -> {
if (prepareRes.failed()) {
closeIfNonNull(transaction).onComplete(ignore -> {
log.error(prepareRes.cause().getMessage(), prepareRes.cause());
replyHandler.handle(Future.failedFuture(prepareRes.cause()));
});
return;
}
PreparedStatement preparedStatement = prepareRes.result();
RowStream<Row> rowStream = new PreparedRowStream(preparedStatement, STREAM_GET_DEFAULT_CHUNK_SIZE, Tuple.tuple());
PostgresClientStreamResult<T> streamResult = new PostgresClientStreamResult<>(resultInfo);
doStreamRowResults(rowStream, clazz, transaction, queryHelper, streamResult, replyHandler);
});
}
use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.
the class AdminAPI method putAdminPostgresDropIndexes.
@Validate
@Override
public void putAdminPostgresDropIndexes(Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
String schema = getSchema(okapiHeaders);
String query = "SELECT * FROM pg_catalog.pg_class c JOIN pg_catalog.pg_index i ON (c.oid = i.indexrelid ) " + "JOIN pg_class t ON (i.indrelid = t.oid ) JOIN pg_namespace n ON (c.relnamespace = n.oid ) " + "WHERE c.relkind = 'i' AND n.nspname = '" + schema + "';";
try {
PostgresClient.getInstance(vertxContext.owner()).select(query, reply -> {
if (reply.succeeded()) {
int[] indexes2delete = new int[] { 0 };
RowSet<Row> rs = reply.result();
StringBuilder concatIndexNames = new StringBuilder();
RowIterator<Row> iterator = rs.iterator();
while (iterator.hasNext()) {
Row row = iterator.next();
String indexName = row.getString(0);
if (!indexName.endsWith("_pkey")) {
indexes2delete[0]++;
if (concatIndexNames.length() > 0) {
concatIndexNames.append(", ");
}
concatIndexNames.append(schema).append(".").append(indexName);
}
}
String dropIndexQuery = "DROP INDEX " + concatIndexNames.toString() + ";";
if (indexes2delete[0] > 0) {
PostgresClient.getInstance(vertxContext.owner()).select(dropIndexQuery, reply2 -> {
if (reply2.succeeded()) {
log.info("Deleted " + indexes2delete[0] + " indexes");
asyncResultHandler.handle(io.vertx.core.Future.succeededFuture(PutAdminPostgresDropIndexesResponse.respond204()));
} else {
log.error(reply.cause().getMessage(), reply.cause());
asyncResultHandler.handle(io.vertx.core.Future.failedFuture(reply2.cause().getMessage()));
}
});
} else {
log.info("No indexes to delete");
asyncResultHandler.handle(io.vertx.core.Future.succeededFuture(PutAdminPostgresDropIndexesResponse.respond400WithTextPlain("No indexes to delete, for tenant " + TenantTool.tenantId(okapiHeaders))));
}
} else {
log.error(reply.cause().getMessage(), reply.cause());
asyncResultHandler.handle(io.vertx.core.Future.failedFuture(reply.cause().getMessage()));
}
});
} catch (Exception e) {
log.error(e.getMessage(), e);
asyncResultHandler.handle(io.vertx.core.Future.failedFuture(e.getMessage()));
}
}
use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.
the class PostgresClient method doStreamRowResults.
/**
* @param transaction the transaction to close, null if not to close
*/
<T> void doStreamRowResults(RowStream<Row> rowStream, Class<T> clazz, Transaction transaction, QueryHelper queryHelper, PostgresClientStreamResult<T> streamResult, Handler<AsyncResult<PostgresClientStreamResult<T>>> replyHandler) {
ResultInfo resultInfo = streamResult.resultInfo();
Promise<PostgresClientStreamResult<T>> promise = Promise.promise();
ResultsHelper<T> resultsHelper = new ResultsHelper<>(clazz);
boolean isAuditFlavored = isAuditFlavored(resultsHelper.clazz);
Map<String, Method> externalColumnSetters = new HashMap<>();
AtomicInteger resultCount = new AtomicInteger();
rowStream.handler(r -> {
try {
// for first row, get column names
if (resultsHelper.offset == 0) {
List<String> columnNames = getColumnNames(r);
collectExternalColumnSetters(columnNames, resultsHelper.clazz, isAuditFlavored, externalColumnSetters);
}
@SuppressWarnings("unchecked") T objRow = (T) deserializeRow(resultsHelper, externalColumnSetters, isAuditFlavored, r);
if (!resultsHelper.facet) {
resultCount.incrementAndGet();
if (!promise.future().isComplete()) {
// end of facets (if any) .. produce result
resultsHelper.facets.forEach((k, v) -> resultInfo.getFacets().add(v));
promise.complete(streamResult);
replyHandler.handle(promise.future());
}
streamResult.fireHandler(objRow);
}
resultsHelper.offset++;
} catch (Exception e) {
streamResult.handler(null);
log.error(e.getMessage(), e);
if (!promise.future().isComplete()) {
promise.complete(streamResult);
replyHandler.handle(promise.future());
}
rowStream.close();
closeIfNonNull(transaction).onComplete((AsyncResult<Void> voidRes) -> streamResult.fireExceptionHandler(e));
}
}).endHandler(v2 -> {
rowStream.close();
closeIfNonNull(transaction).onComplete(ignore -> {
resultInfo.setTotalRecords(getTotalRecords(resultCount.get(), resultInfo.getTotalRecords(), queryHelper.offset, queryHelper.limit));
try {
if (!promise.future().isComplete()) {
promise.complete(streamResult);
replyHandler.handle(promise.future());
}
streamResult.fireEndHandler();
} catch (Exception ex) {
streamResult.fireExceptionHandler(ex);
}
});
}).exceptionHandler(e -> {
rowStream.close();
closeIfNonNull(transaction).onComplete(ignore -> {
if (!promise.future().isComplete()) {
promise.complete(streamResult);
replyHandler.handle(promise.future());
}
streamResult.fireExceptionHandler(e);
});
});
}
Aggregations