3030import java .sql .*;
3131import java .util .*;
3232import java .util .concurrent .*;
33+ import java .util .regex .Pattern ;
3334
3435public 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}
0 commit comments