Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend sql-db/hibernate-reactive and sql-db/vertx-sql with oracle #563

Merged
merged 1 commit into from
Jun 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ Covered DBs:
- MySQL
- DB2
- MSSQL
- Oracle

### `sql-db/vertx-sql`
Quarkus / Vertx SQL exploratory testing. A flight search engine in order to test Quarkus Reactive SQL extensions. A detailed description can be found in sql-db/vertx-sql/README.md
Expand Down
4 changes: 4 additions & 0 deletions sql-db/hibernate-reactive/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-mssql-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-oracle-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.quarkus.ts.hibernate.reactive;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.OracleService;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.Container;
import io.quarkus.test.services.QuarkusApplication;

@QuarkusScenario
public class OracleDatabaseIT extends AbstractDatabaseHibernateReactiveIT {

private static final String ORACLE_USER = "quarkus_test";
private static final String ORACLE_PASSWORD = "quarkus_test";
private static final String ORACLE_DATABASE = "quarkus_test";
private static final int ORACLE_PORT = 1521;

@Container(image = "${oracle.image}", port = ORACLE_PORT, expectedLog = "DATABASE IS READY TO USE!")
static OracleService database = new ProvisionalOracleService()
.with(ORACLE_USER, ORACLE_PASSWORD, ORACLE_DATABASE);

@QuarkusApplication
static RestService app = new RestService().withProperties("oracle.properties")
.withProperty("quarkus.datasource.username", ORACLE_USER)
.withProperty("quarkus.datasource.password", ORACLE_PASSWORD)
.withProperty("quarkus.datasource.reactive.url", database::getReactiveUrl);

@Override
protected RestService getApp() {
return app;
}

@Test
@Override
@Disabled("https://github.com/quarkusio/quarkus/issues/24501")
public void deleteAuthorById() {
}

@Test
@Override
@Disabled("https://github.com/quarkusio/quarkus/issues/24501")
public void setConvertedValue() {
}

@Test
@Override
@Disabled("https://github.com/quarkusio/quarkus/issues/24501")
public void ensureSessionIsPropagatedOnReactiveTransactions() {
}

// TODO: Remove after https://github.com/quarkus-qe/quarkus-test-framework/issues/503 is resolved
private static class ProvisionalOracleService extends OracleService {
@Override
public String getReactiveUrl() {
return getHost().replace("http://", getJdbcName() + ":thin:@") + ":" + getPort() + "/"
+ getDatabase();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.quarkus.ts.hibernate.reactive.openshift;

import org.junit.jupiter.api.Disabled;

import io.quarkus.test.scenarios.OpenShiftScenario;
import io.quarkus.ts.hibernate.reactive.OracleDatabaseIT;

@Disabled("https://issues.redhat.com/browse/QUARKUS-1164?focusedCommentId=18977100&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-18977100")
@OpenShiftScenario
public class OpenShiftOracleIT extends OracleDatabaseIT {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
quarkus.datasource.db-kind=oracle
quarkus.hibernate-orm.sql-load-script=oracle_import.sql
quarkus.hibernate-orm.database.generation=create
11 changes: 11 additions & 0 deletions sql-db/hibernate-reactive/src/test/resources/oracle_import.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
DROP TABLE authors;
CREATE TABLE AUTHORS(ID NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, NAME VARCHAR(100) NOT NULL);
INSERT INTO authors(id,name) VALUES (1, 'Homer');
INSERT INTO authors(id,name) VALUES (2, 'Vern');
INSERT INTO authors(id,name) VALUES (3, 'Dlugi');
INSERT INTO authors(id,name) VALUES (4, 'Kahneman');
DROP TABLE books;
CREATE TABLE books(id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, author INT references authors(id) , title VARCHAR(500) NOT NULL, isbn VARCHAR(50));
INSERT INTO books(author, title) VALUES (3, 'Slovník');
INSERT INTO books(author, title, isbn) VALUES (4, 'Thinking fast and slow', '978-0374275631');
INSERT INTO books(author, title) VALUES (4, 'Attention and Effort');
3 changes: 2 additions & 1 deletion sql-db/vertx-sql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ To compile and run this demo you will need:
- PostgreSQL
- MySQL
- DB2
- Oracle

## Scope of the testing

Quarkus / Vertx SQL exploratory testing

* Quarkus Vertx Reactive Routes (annotations)
* OpenAPI from annotations
* Reactive SQL / PostgreSQL / MySQL / DB2
* Reactive SQL / PostgreSQL / MySQL / DB2 / Oracle
* Select / insert statements
* Transaction statement between several tables
* Error mapping through routes
Expand Down
8 changes: 8 additions & 0 deletions sql-db/vertx-sql/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-mssql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-oracle-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-oracle</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.vertx.mutiny.db2client.DB2Pool;
import io.vertx.mutiny.mssqlclient.MSSQLPool;
import io.vertx.mutiny.mysqlclient.MySQLPool;
import io.vertx.mutiny.oracleclient.OraclePool;
import io.vertx.mutiny.pgclient.PgPool;

/**
Expand Down Expand Up @@ -63,6 +64,11 @@ public class Application {
@IfBuildProfile("mssql")
MSSQLPool mssql;

@Inject
@Named("oracle")
@IfBuildProfile("oracle")
OraclePool oracle;

void onStart(@Observes StartupEvent ev) {
LOGGER.info("The application is starting with profile " + ProfileManager.getActiveProfile());

Expand All @@ -81,6 +87,8 @@ synchronized DbPoolService pool() {
return new DbPoolService(db2, "\"" + db2DbName + "\"", selectedDB);
case "mssql":
return new DbPoolService(mssql, null, selectedDB);
case "oracle":
return new DbPoolService(oracle, null, selectedDB);
default:
return new DbPoolService(postgresql, postgresqlDbName, selectedDB);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void setNif(String nif) {

public Uni<Long> save(DbPoolService sqlClient) {
return SqlClientHelper.inTransactionUni(sqlClient, tx -> address.save(sqlClient).onItem().transformToUni(address_id -> {
List<String> fieldsNames = Arrays.asList("nif,name,last_name,contact_number,created_at, address_id".split(","));
List<String> fieldsNames = Arrays.asList("nif,name,last_name,contact_number,created_at,address_id".split(","));
List<Object> fieldsValues = Stream
.of(getNif(), getName(), getLastName(), getContactNumber(), getCreatedAt(), address_id)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javax.validation.ConstraintViolationException;

import io.quarkus.vertx.web.Route;
import io.vertx.core.VertxException;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonObject;
Expand Down Expand Up @@ -33,10 +34,18 @@ void databaseDb2ConstraintFailure(DB2Exception e, HttpServerResponse response) {
}

@Route(path = "*", type = Route.HandlerType.FAILURE, produces = "application/json")
void databaseDb2ConstraintFailure(MSSQLException e, HttpServerResponse response) {
void databaseMssqlConstraintFailure(MSSQLException e, HttpServerResponse response) {
response.setStatusCode(400).end(Json.encode(new JsonObject().put("msg", e.getMessage())));
}

// TODO: https://github.com/quarkusio/quarkus/issues/24264 - No Oracle-specific exception available
@Route(path = "/*", type = Route.HandlerType.FAILURE, produces = "application/json")
void databaseOracleConstraintFailure(VertxException e, HttpServerResponse response) {
if (e.getMessage().contains("Error Msg = ORA")) {
response.setStatusCode(400).end(Json.encode(new JsonObject().put("msg", e.getMessage())));
}
}

@Route(path = "*", type = Route.HandlerType.FAILURE, produces = "application/json")
public void exceptions(ConstraintViolationException e, HttpServerResponse res) {
res.setStatusCode(400).end(handler -> e.getConstraintViolations().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
import java.util.stream.Collectors;

import io.smallrye.mutiny.Uni;
import io.vertx.core.json.JsonArray;
import io.vertx.mutiny.oracleclient.OracleClient;
import io.vertx.mutiny.sqlclient.Pool;
import io.vertx.mutiny.sqlclient.SqlClientHelper;
import io.vertx.oracleclient.OraclePrepareOptions;
import io.vertx.sqlclient.PropertyKind;

public class DbPoolService extends Pool {

private final static PropertyKind<Long> LAST_INSERTED_ID = PropertyKind.create("last-inserted-id", Long.class);
private static final String ORACLE_AUTO_GENERATED_KEY_NAME = "ID";
private static final OraclePrepareOptions ORACLE_AUTO_GENERATED_KEYS_OPTIONS = new OraclePrepareOptions()
.setAutoGeneratedKeysIndexes(new JsonArray().add(ORACLE_AUTO_GENERATED_KEY_NAME));
private final String databaseName;
private final String selectedDb;

Expand All @@ -34,6 +40,8 @@ public Uni<Long> save(String tableName, List<String> fieldsNames, List<Object> f
return saveDb2(tableName, fieldsNames, fieldsValues);
case "mssql":
return saveMS(tableName, fieldsNames, fieldsValues);
case "oracle":
return saveOracle(tableName, fieldsNames, fieldsValues);
default:
return savePg(tableName, fieldsNames, fieldsValues);
}
Expand Down Expand Up @@ -91,6 +99,20 @@ protected Uni<Long> saveDb2(String tableName, List<String> fieldsNames, List<Obj
});
}

protected Uni<Long> saveOracle(String tableName, List<String> fieldsNames, List<Object> fieldsValues) {
return SqlClientHelper.inTransactionUni(this, tx -> {
String fields = tableFieldsToString(fieldsNames);
String values = tableFieldsValuesToString(fieldsValues);

return tx
.preparedQuery("INSERT INTO " + getTableName(tableName) + " (" + fields + ") VALUES (" + values + ")",
ORACLE_AUTO_GENERATED_KEYS_OPTIONS)
.execute()
.onItem()
.transform(rows -> rows.property(OracleClient.GENERATED_KEYS).getLong(ORACLE_AUTO_GENERATED_KEY_NAME));
});
}

private String tableFieldsToString(List<String> fieldsNames) {
return String.join(",", fieldsNames);
}
Expand Down
13 changes: 13 additions & 0 deletions sql-db/vertx-sql/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,16 @@ quarkus.datasource.mssql.reactive.url=sqlserver://localhost:1433/msdb
quarkus.flyway.mssql.schemas=msdb
quarkus.datasource.mssql.jdbc.url=jdbc:sqlserver://localhost:1433;databaseName=msdb
quarkus.flyway.mssql.locations=db/migration/mssql,db/migration/common

## Oracle
## Database
%oracle.app.selected.db=oracle
quarkus.datasource.oracle.reactive=true
quarkus.datasource.oracle.db-kind=oracle
quarkus.datasource.oracle.username=test
quarkus.datasource.oracle.password=test
quarkus.datasource.oracle.reactive.url=oracle:thin:@localhost:1521:amadeus

## Flyway
quarkus.datasource.oracle.jdbc.url=jdbc:oracle:thin:@localhost:1521:amadeus
quarkus.flyway.oracle.locations=db/migration/oracle,db/migration/common
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@

CREATE TABLE airports (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
iata_code VARCHAR(100) NOT NULL UNIQUE,
city VARCHAR(100) NOT NULL
);

CREATE TABLE airlines (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
iata_code VARCHAR(100) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
infant_price FLOAT(7)
);

CREATE TABLE flights (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
origin VARCHAR(100) NOT NULL,
destination VARCHAR(100) NOT NULL,
flight_code VARCHAR(100) NOT NULL,
base_price SMALLINT NOT NULL
);

CREATE TABLE pricingRules (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
days_to_departure SMALLINT NOT NULL,
until SMALLINT NOT NULL,
percentage SMALLINT NOT NULL
);

CREATE TABLE address (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
street VARCHAR(300) NOT NULL,
block_number VARCHAR(20) NOT NULL,
zip_code VARCHAR(20) NOT NULL,
city VARCHAR(150) NOT NULL,
country VARCHAR(200) NOT NULL,
created_at INT NOT NULL,
updated_at INT
);

CREATE TABLE passenger (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
nif VARCHAR(15) NOT NULL,
name VARCHAR(25) NOT NULL,
last_name VARCHAR(55) NOT NULL,
contact_number VARCHAR(20) NOT NULL,
created_at INT NOT NULL,
updated_at INT,
address_id NUMBER,
CONSTRAINT fk_address FOREIGN KEY(address_id) REFERENCES address(id) ON DELETE SET NULL
);

CREATE TABLE basket (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
flight VARCHAR(10) NOT NULL,
price NUMERIC NOT NULL,
created_at INT NOT NULL,
updated_at INT,
passenger_id NUMBER,
CONSTRAINT fk_passenger FOREIGN KEY(passenger_id) REFERENCES passenger(id) ON DELETE SET NULL
);

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.quarkus.ts.vertx.sql.handlers;

import io.quarkus.test.bootstrap.OracleService;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.Container;
import io.quarkus.test.services.QuarkusApplication;

@QuarkusScenario
public class OracleHandlerIT extends CommonTestCases {
private static final int ORACLE_PORT = 1521;
private static final String DATABASE = "amadeus";

@Container(image = "${oracle.image}", port = ORACLE_PORT, expectedLog = "DATABASE IS READY TO USE!")
static OracleService oracle = new ProvisionalOracleService()
.with("test", "test", DATABASE);

@QuarkusApplication
static final RestService app = new RestService()
.withProperty("quarkus.datasource.oracle.username", oracle::getUser)
.withProperty("quarkus.datasource.oracle.password", oracle::getPassword)
.withProperty("quarkus.datasource.oracle.jdbc.url", oracle::getJdbcUrl)
.withProperty("quarkus.datasource.oracle.reactive.url", oracle::getReactiveUrl)
.withProperty("app.selected.db", "oracle")
// Enable Flyway for Oracle
.withProperty("quarkus.flyway.oracle.migrate-at-start", "true");

// TODO: Remove after https://github.com/quarkus-qe/quarkus-test-framework/issues/503 is resolved
private static class ProvisionalOracleService extends OracleService {
@Override
public String getReactiveUrl() {
return getHost().replace("http://", getJdbcName() + ":thin:@") + ":" + getPort() + "/" + getDatabase();
}
}
}