Skip to content

Commit 2fee22f

Browse files
authored
Update the file scanner to look for semicolons as a delimiter only when (#251)
at the end of a line. Also update the database exist check to not use try with resources because it closes out the ResultSet before we can read it when connecting to a Postgres database.
1 parent 784fef7 commit 2fee22f

File tree

3 files changed

+52
-25
lines changed

3 files changed

+52
-25
lines changed

resources/custom-resources/rds-bootstrap/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ limitations under the License.
133133
<dependency>
134134
<groupId>org.postgresql</groupId>
135135
<artifactId>postgresql</artifactId>
136-
<version>42.3.3</version>
136+
<version>42.4.0</version>
137137
</dependency>
138138
<dependency>
139139
<groupId>org.mariadb.jdbc</groupId>
@@ -143,7 +143,7 @@ limitations under the License.
143143
<dependency>
144144
<groupId>com.microsoft.sqlserver</groupId>
145145
<artifactId>mssql-jdbc</artifactId>
146-
<version>8.2.2.jre11</version>
146+
<version>10.2.0.jre11</version>
147147
</dependency>
148148
</dependencies>
149149

resources/custom-resources/rds-bootstrap/src/main/java/com/amazon/aws/partners/saasfactory/saasboost/RdsBootstrap.java

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@
3030
import java.sql.*;
3131
import java.util.*;
3232
import java.util.concurrent.*;
33+
import java.util.regex.Pattern;
3334

3435
public class RdsBootstrap implements RequestHandler<Map<String, Object>, Object> {
3536

3637
private static final Logger LOGGER = LoggerFactory.getLogger(RdsBootstrap.class);
3738
private static final String AWS_REGION = System.getenv("AWS_REGION");
39+
static final String SQL_STATEMENT_DELIMITER = ";\r?\n";
3840
private final S3Client s3;
3941
private final SsmClient ssm;
4042

@@ -127,7 +129,7 @@ public Object handleRequest(Map<String, Object> event, Context context) {
127129
Statement sql = conn.createStatement()) {
128130
conn.setAutoCommit(false);
129131
Scanner sqlScanner = new Scanner(bootstrapSql, StandardCharsets.UTF_8);
130-
sqlScanner.useDelimiter(";");
132+
sqlScanner.useDelimiter(Pattern.compile(SQL_STATEMENT_DELIMITER));
131133
while (sqlScanner.hasNext()) {
132134
String ddl = sqlScanner.next().trim();
133135
if (!ddl.isEmpty()) {
@@ -178,31 +180,45 @@ public Object handleRequest(Map<String, Object> event, Context context) {
178180
return null;
179181
}
180182

181-
private static boolean databaseExists(Connection conn, String engine, String database) throws SQLException {
183+
static boolean databaseExists(Connection conn, String engine, String database) throws SQLException {
182184
boolean databaseExists = false;
183-
ResultSet rs;
184-
if ("postgresql".equals(engine)) {
185-
// Postgres doesn't support multiple databases (catalogs) per connection, so we can't use the JDBC
186-
// metadata to get a list of all the databases on the host like you can with MySQL/MariaDB
187-
try (Statement sql = conn.createStatement()) {
185+
Statement sql = null;
186+
ResultSet rs = null;
187+
try {
188+
if ("postgresql".equals(engine)) {
189+
// Postgres doesn't support multiple databases (catalogs) per connection, so we can't use the JDBC
190+
// metadata to get a list of all the databases on the host like you can with MySQL/MariaDB
191+
sql = conn.createStatement();
188192
rs = sql.executeQuery("SELECT datname AS TABLE_CAT FROM pg_database WHERE datistemplate = false");
193+
} else {
194+
DatabaseMetaData dbMetaData = conn.getMetaData();
195+
rs = dbMetaData.getCatalogs();
189196
}
190-
} else {
191-
DatabaseMetaData dbMetaData = conn.getMetaData();
192-
rs = dbMetaData.getCatalogs();
193-
}
194-
while (rs.next()) {
195-
LOGGER.info("Database exists check: TABLE_CAT = {}", rs.getString("TABLE_CAT"));
196-
if (rs.getString("TABLE_CAT").equals(database)) {
197-
databaseExists = true;
198-
break;
197+
if (rs != null) {
198+
while (rs.next()) {
199+
LOGGER.info("Database exists check: TABLE_CAT = {}", rs.getString("TABLE_CAT"));
200+
if (rs.getString("TABLE_CAT").equals(database)) {
201+
databaseExists = true;
202+
break;
203+
}
204+
}
205+
} else {
206+
LOGGER.error("No database catalog result set!");
199207
}
208+
} catch (SQLException e) {
209+
LOGGER.error("Error checking if database exists", e);
210+
LOGGER.error(Utils.getFullStackTrace(e));
211+
throw e;
212+
} finally {
213+
// Do our own resource cleanup instead of using try...with resources because in the PostgreSQL
214+
// branch the Statement object will close out our ResultSet before we can loop over it.
215+
closeQuietly(rs);
216+
closeQuietly(sql);
200217
}
201-
rs.close();
202218
return databaseExists;
203219
}
204220

205-
public static void createdb(Connection conn, String engine, String database) throws SQLException {
221+
static void createdb(Connection conn, String engine, String database) throws SQLException {
206222
LOGGER.info("Creating {} database {}", engine, database);
207223
try (Statement create = conn.createStatement()) {
208224
if (engine.contains("postgresql")) {
@@ -224,7 +240,7 @@ public static void createdb(Connection conn, String engine, String database) thr
224240
}
225241
}
226242

227-
private static String jdbcUrl(String type, String driverClassName, String host, String port, String database) {
243+
static String jdbcUrl(String type, String driverClassName, String host, String port, String database) {
228244
StringBuilder url = new StringBuilder("jdbc:");
229245
url.append(type);
230246
if (!"oracle.jdbc.driver.OracleDriver".equals(driverClassName)) {
@@ -247,7 +263,7 @@ private static String jdbcUrl(String type, String driverClassName, String host,
247263
return url.toString();
248264
}
249265

250-
private static String typeFromPort(String port) {
266+
static String typeFromPort(String port) {
251267
String type;
252268
switch (port) {
253269
case "5432":
@@ -268,7 +284,7 @@ private static String typeFromPort(String port) {
268284
return type;
269285
}
270286

271-
private static String driverClassNameFromPort(String port) {
287+
static String driverClassNameFromPort(String port) {
272288
String driverClassName;
273289
switch (port) {
274290
case "5432":
@@ -288,4 +304,14 @@ private static String driverClassNameFromPort(String port) {
288304
}
289305
return driverClassName;
290306
}
307+
308+
static void closeQuietly(AutoCloseable resource) {
309+
if (resource != null) {
310+
try {
311+
resource.close();
312+
} catch (Exception e) {
313+
LOGGER.warn("Resource close failed", e);
314+
}
315+
}
316+
}
291317
}

resources/custom-resources/rds-bootstrap/src/test/java/com/amazon/aws/partners/saasfactory/saasboost/RdsBootstrapTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@
2222
import java.util.ArrayList;
2323
import java.util.List;
2424
import java.util.Scanner;
25+
import java.util.regex.Pattern;
2526

2627
import static org.junit.Assert.*;
2728

2829
public class RdsBootstrapTest {
2930

3031
@Test
31-
public void testSqlScanner() throws Exception {
32+
public void testSqlScanner() {
3233
InputStream bootstrapSQL = Thread.currentThread().getContextClassLoader().getResourceAsStream("bootstrap.sql");
3334
Scanner sqlScanner = new Scanner(bootstrapSQL, "UTF-8");
34-
sqlScanner.useDelimiter(";");
35+
sqlScanner.useDelimiter(Pattern.compile(RdsBootstrap.SQL_STATEMENT_DELIMITER));
3536
List<String> sql = new ArrayList<>();
3637
while (sqlScanner.hasNext()) {
3738
String ddl = sqlScanner.next().trim();

0 commit comments

Comments
 (0)