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

[2.2] Reactive MS SQL client support #263

Merged
merged 1 commit into from
Sep 13, 2021
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
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
package io.quarkus.ts.sqldb.sqlapp;

import io.quarkus.test.bootstrap.DefaultService;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.bootstrap.SqlServerService;
import io.quarkus.test.scenarios.OpenShiftScenario;
import io.quarkus.test.services.Container;
import io.quarkus.test.services.QuarkusApplication;

@OpenShiftScenario
public class OpenShiftMssqlDatabaseIT extends AbstractSqlDatabaseIT {
private static final String MSSQL_PASSWORD = "QuArKuS_tEsT";
private static final String DATABASE = "msdb";

static final int MSSQL_PORT = 1433;

@Container(image = "${mssql.image}", port = MSSQL_PORT, expectedLog = "Service Broker manager has started")
static SqlServerService mssql = new SqlServerService();
//fixme Replace with SqlServerService when https://github.com/quarkus-qe/quarkus-test-framework/issues/251 will be solved
static DefaultService mssql = new DefaultService()
.withProperty("ACCEPT_EULA", "Y")
.withProperty("SA_PASSWORD", MSSQL_PASSWORD);

@QuarkusApplication
static RestService app = new RestService()
static final RestService app = new RestService()
.withProperties("mssql.properties")
.withProperty("quarkus.datasource.username", mssql.getUser())
.withProperty("quarkus.datasource.password", mssql.getPassword())
.withProperty("quarkus.datasource.jdbc.url", mssql::getJdbcUrl);
.withProperty("quarkus.datasource.username", "sa")
.withProperty("quarkus.datasource.password", MSSQL_PASSWORD)
.withProperty("quarkus.datasource.jdbc.url",
() -> mssql.getHost().replace("http", "jdbc:sqlserver") + ":" +
mssql.getPort() + ";databaseName=" + DATABASE);
}
8 changes: 8 additions & 0 deletions sql-db/vertx-sql/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-db2</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-mssql-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-mssql</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 @@ -21,10 +21,13 @@
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.jackson.DatabindCodec;
import io.vertx.mutiny.db2client.DB2Pool;
import io.vertx.mutiny.mssqlclient.MSSQLPool;
import io.vertx.mutiny.mysqlclient.MySQLPool;
import io.vertx.mutiny.pgclient.PgPool;

/** Application is used as a main class in order to setup some global configuration */
/**
* Application is used as a main class in order to setup some global configuration
*/
@ApplicationScoped
public class Application {

Expand Down Expand Up @@ -55,6 +58,11 @@ public class Application {
@IfBuildProfile("db2")
DB2Pool db2;

@Inject
@Named("mssql")
@IfBuildProfile("mssql")
MSSQLPool mssql;

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

Expand All @@ -71,6 +79,8 @@ synchronized DbPoolService pool() {
return new DbPoolService(mysql, mysqlDbName, selectedDB);
case "db2":
return new DbPoolService(db2, "\"" + db2DbName + "\"", selectedDB);
case "mssql":
return new DbPoolService(mssql, null, selectedDB);
default:
return new DbPoolService(postgresql, postgresqlDbName, selectedDB);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ protected static Multi<Airline> fromSet(RowSet<Row> rows) {
}

public static Multi<Airline> findAll(DbPoolService client) {
return client.query("SELECT * FROM " + client.getDatabaseName() + ".airlines").execute().onItem()
return client.query("SELECT * FROM " + client.getTableName("airlines")).execute().onItem()
.transformToMulti(Airline::fromSet);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ protected static Multi<Airport> fromSet(RowSet<Row> rows) {
}

public static Multi<Airport> findAll(DbPoolService client) {
return client.query("SELECT * FROM " + client.getDatabaseName() + ".airports").execute().onItem()
return client.query("SELECT * FROM " + client.getTableName("airports")).execute().onItem()
.transformToMulti(Airport::fromSet);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ protected static Multi<Flight> fromSet(RowSet<Row> rows) {
}

public static Multi<Flight> findAll(DbPoolService client) {
return client.query("SELECT * FROM " + client.getDatabaseName() + ".flights").execute().onItem()
return client.query("SELECT * FROM " + client.getTableName("flights")).execute().onItem()
.transformToMulti(Flight::fromSet);
}

Expand All @@ -64,7 +64,7 @@ public static Uni<List<Flight>> findAllAsList(DbPoolService client) {
}

public static Multi<Flight> findByOriginDestination(DbPoolService client, String origin, String destination) {
String query = String.format("SELECT * FROM " + client.getDatabaseName() + ".flights where %s = '%s' and %s = '%s'",
String query = String.format("SELECT * FROM " + client.getTableName("flights") + " where %s = '%s' and %s = '%s'",
QUALIFIED_ORIGIN_NAME, origin, QUALIFIED_DESTINATION_NAME, destination);
return client.query(query).execute().onItem().transformToMulti(Flight::fromSet);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected static Multi<PricingRules> fromSet(RowSet<Row> rows) {
}

public static Multi<PricingRules> findAll(DbPoolService client) {
return client.query("SELECT * FROM " + client.getDatabaseName() + ".pricingRules").execute().onItem()
return client.query("SELECT * FROM " + client.getTableName("pricingRules")).execute().onItem()
.transformToMulti(PricingRules::fromSet);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonObject;
import io.vertx.db2client.DB2Exception;
import io.vertx.mssqlclient.MSSQLException;
import io.vertx.mysqlclient.MySQLException;
import io.vertx.pgclient.PgException;

Expand All @@ -31,6 +32,11 @@ void databaseDb2ConstraintFailure(DB2Exception e, HttpServerResponse response) {
response.setStatusCode(400).end(Json.encode(new JsonObject().put("msg", e.getMessage())));
}

@Route(path = "/*", type = Route.HandlerType.FAILURE, produces = "application/json")
void databaseDb2ConstraintFailure(MSSQLException e, HttpServerResponse response) {
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 @@ -20,8 +20,10 @@ public DbPoolService(Pool delegate, String dbName, String selectedDb) {
this.selectedDb = selectedDb;
}

public String getDatabaseName() {
return databaseName;
public String getTableName(String table) {
return null == databaseName
? table
: databaseName + "." + table;
}

public Uni<Long> save(String tableName, List<String> fieldsNames, List<Object> fieldsValues) {
Expand All @@ -30,18 +32,34 @@ public Uni<Long> save(String tableName, List<String> fieldsNames, List<Object> f
return saveMysql(tableName, fieldsNames, fieldsValues);
case "db2":
return saveDb2(tableName, fieldsNames, fieldsValues);
case "mssql":
return saveMS(tableName, fieldsNames, fieldsValues);
default:
return savePg(tableName, fieldsNames, fieldsValues);
}
}

private Uni<Long> saveMS(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
+ "); SELECT SCOPE_IDENTITY() as id;")
.execute()
.map(r -> r.iterator().next().getLong("id"));
});
}

protected Uni<Long> savePg(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 " + getDatabaseName() + "." + tableName + " (" + fields + ") VALUES (" + values
.preparedQuery("INSERT INTO " + getTableName(tableName) + " (" + fields + ") VALUES (" + values
+ ") RETURNING id")
.execute().onItem().transform(id -> id.iterator().next().getLong("id"));
});
Expand All @@ -54,7 +72,7 @@ protected Uni<Long> saveMysql(String tableName, List<String> fieldsNames, List<O

return tx
.preparedQuery(
"INSERT INTO " + getDatabaseName() + "." + tableName + " (" + fields + ") VALUES (" + values + ")")
"INSERT INTO " + getTableName(tableName) + " (" + fields + ") VALUES (" + values + ")")
.execute()
.onItem().invoke(r -> this.query("SELECT LAST_INSERT_ID();"))
.onItem().transform(id -> (Long) id.getDelegate().property(LAST_INSERTED_ID));
Expand All @@ -67,7 +85,7 @@ protected Uni<Long> saveDb2(String tableName, List<String> fieldsNames, List<Obj
String values = tableFieldsValuesToString(fieldsValues);

return tx
.preparedQuery("select id from NEW TABLE (INSERT INTO " + getDatabaseName() + "." + tableName + " ("
.preparedQuery("select id from NEW TABLE (INSERT INTO " + getTableName(tableName) + " ("
+ fields + ") VALUES (" + values + "))")
.execute().onItem().transform(id -> id.iterator().next().getLong("id"));
});
Expand All @@ -88,5 +106,4 @@ private String tableFieldsValuesToString(List<Object> fieldsValues) {
return content;
}).collect(Collectors.joining(",", "", ""));
}

}
20 changes: 16 additions & 4 deletions sql-db/vertx-sql/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ quarkus.datasource.reactive.reconnect-attempts=3
quarkus.datasource.reactive.reconnect-interval=3

## Flyway
quarkus.flyway.migrate-at-start=true
quarkus.flyway.migrate-at-start=false
quarkus.flyway.schemas=amadeus
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/amadeus
quarkus.flyway.locations=db/migration/postgresql,db/migration/common
Expand All @@ -33,7 +33,6 @@ quarkus.datasource.mysql.password=test
quarkus.datasource.mysql.reactive.url=mysql://localhost:3306/amadeus

# Flyway
quarkus.flyway.mysql.migrate-at-start=true
quarkus.flyway.mysql.schemas=amadeus
quarkus.datasource.mysql.jdbc.url=jdbc:mysql://localhost:3306/amadeus?useSSL=false
quarkus.flyway.mysql.locations=db/migration/mysql,db/migration/common
Expand All @@ -49,7 +48,20 @@ quarkus.datasource.db2.password=test
quarkus.datasource.db2.reactive.url=vertx-reactive:db2://localhost:50000/amadeus

# Flyway
quarkus.flyway.db2.migrate-at-start=true
quarkus.flyway.db2.schemas=amadeus
quarkus.datasource.db2.jdbc.url=jdbc:db2://localhost:50000/amadeus
quarkus.flyway.db2.locations=db/migration/db2,db/migration/common
quarkus.flyway.db2.locations=db/migration/db2,db/migration/common

## MS SQL
## Database
%mssql.app.selected.db=mssql
quarkus.datasource.mssql.reactive=true
quarkus.datasource.mssql.db-kind=mssql
quarkus.datasource.mssql.username=sa
quarkus.datasource.mssql.password=QuArKuS_tEsT
quarkus.datasource.mssql.reactive.url=vertx-reactive:sqlserver://localhost:1433/msdb

# Flyway
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
CREATE TABLE airports (
id INT NOT NULL IDENTITY(1,1),
iata_code VARCHAR(100) NOT NULL,
city VARCHAR(100) NOT NULL,
PRIMARY KEY(id)
);

CREATE TABLE airlines (
id INT NOT NULL IDENTITY(1,1),
iata_code VARCHAR(100) NOT NULL,
name VARCHAR(100) NOT NULL,
infant_price FLOAT(3),
PRIMARY KEY(id)
);

CREATE TABLE flights (
id INT NOT NULL IDENTITY(1,1),
origin VARCHAR(100) NOT NULL,
destination VARCHAR(100) NOT NULL,
flight_code VARCHAR(100) NOT NULL,
base_price INTEGER NOT NULL,
PRIMARY KEY(id)
);

CREATE TABLE pricingRules (
id INT NOT NULL IDENTITY(1,1),
days_to_departure INTEGER NOT NULL,
until INTEGER NOT NULL,
percentage INTEGER NOT NULL,
PRIMARY KEY(id)
);

CREATE TABLE address (
id INT NOT NULL IDENTITY(1,1),
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 BIGINT NOT NULL,
updated_at BIGINT,
PRIMARY KEY(id)
);

CREATE TABLE passenger (
id INT NOT NULL IDENTITY(1,1),
nif VARCHAR(10) NOT NULL,
name VARCHAR(25) NOT NULL,
last_name VARCHAR(55) NOT NULL,
contact_number VARCHAR(20) NOT NULL,
created_at BIGINT NOT NULL,
updated_at BIGINT,
address_id INT,
PRIMARY KEY(id),
FOREIGN KEY (address_id) REFERENCES address(id) ON DELETE SET NULL
);

CREATE TABLE basket (
id INT NOT NULL IDENTITY(1,1),
flight VARCHAR(10) NOT NULL,
price NUMERIC NOT NULL,
created_at BIGINT NOT NULL,
updated_at BIGINT,
passenger_id INT,
PRIMARY KEY(id),
FOREIGN KEY (passenger_id) REFERENCES passenger(id) ON DELETE SET NULL
);
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ public class Db2HandlerIT extends CommonTestCases {
private static final String DATABASE = "amadeus";

@Container(image = "${db2.image}", port = 50000, expectedLog = "Setup has completed")
static Db2Service db2 = new Db2Service()
.with("test", "test", DATABASE);
static Db2Service db2 = new Db2Service().with("test", "test", DATABASE);

@QuarkusApplication
static final RestService app = new RestService()
.withProperty("quarkus.datasource.db2.jdbc.url", db2::getJdbcUrl)
.withProperty("quarkus.datasource.db2.reactive.url", db2::getReactiveUrl)
.withProperty("quarkus.datasource.db2.jdbc.url",
() -> db2.getHost().replace("http", "jdbc:db2") + ":" +
db2.getPort() + "/" + DATABASE)
.withProperty("quarkus.datasource.db2.reactive.url",
() -> db2.getHost().replace("http", "db2") + ":" +
db2.getPort() + "/" + DATABASE)
.withProperty("app.selected.db", "db2")
// Enable Flyway for DB2
.withProperty("quarkus.flyway.db2.migrate-at-start", "true")
// Disable Flyway for MySQL
.withProperty("quarkus.flyway.mysql.migrate-at-start", "false")
// Disable Flyway for Postgresql
.withProperty("quarkus.flyway.migrate-at-start", "false");
.withProperty("quarkus.flyway.db2.migrate-at-start", "true");

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

import io.quarkus.test.bootstrap.DefaultService;
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 MSsqlHandlerIT extends CommonTestCases {
private static final String MSSQL_PASSWORD = "QuArKuS_tEsT";
private static final String DATABASE = "msdb";
private static final int MSSQL_PORT = 1433;

//fixme Replace with SqlServerService when https://github.com/quarkus-qe/quarkus-test-framework/issues/251 will be solved
@Container(image = "${mssql.image}", port = MSSQL_PORT, expectedLog = "Service Broker manager has started")
static DefaultService mssql = new DefaultService()
.withProperty("ACCEPT_EULA", "Y")
.withProperty("SA_PASSWORD", MSSQL_PASSWORD);

@QuarkusApplication
static final RestService app = new RestService()
.withProperty("quarkus.datasource.mssql.jdbc.url",
() -> mssql.getHost().replace("http", "jdbc:sqlserver") + ":" +
mssql.getPort() + ";databaseName=" + DATABASE)
.withProperty("quarkus.datasource.mssql.reactive.url",
() -> mssql.getHost().replace("http", "sqlserver") + ":" +
mssql.getPort() + "/" + DATABASE)
.withProperty("app.selected.db", "mssql")
// Enable Flyway for MySQL
.withProperty("quarkus.flyway.mssql.migrate-at-start", "true");
}
Loading