@@ -177,13 +177,37 @@ async fn smoke_example(example: &ExampleApp, database_url: &str) {
177177}
178178
179179async fn prepare_postgres_base_url ( ) -> Option < String > {
180+ if let Some ( database_url) = database_url_from_env ( & [ "postgres" , "postgresql" ] ) {
181+ let admin_url = replace_database_name ( & database_url, "postgres" ) ;
182+ let mut conn = sqlx:: PgConnection :: connect ( & admin_url)
183+ . await
184+ . unwrap_or_else ( |err| panic ! ( "DATABASE_URL points to PostgreSQL but connecting to {admin_url} failed: {err:#}" ) ) ;
185+ conn. execute ( "SELECT 1" ) . await . unwrap_or_else ( |err| {
186+ panic ! ( "DATABASE_URL points to PostgreSQL but validation failed: {err:#}" )
187+ } ) ;
188+ return Some ( replace_database_name ( & database_url, "sqlpage_examples" ) ) ;
189+ }
190+
180191 let admin_url = "postgres://root:Password123!@localhost/postgres" ;
181192 let mut conn = sqlx:: PgConnection :: connect ( admin_url) . await . ok ( ) ?;
182193 conn. execute ( "SELECT 1" ) . await . ok ( ) ?;
183194 Some ( "postgres://root:Password123!@localhost/sqlpage_examples" . to_string ( ) )
184195}
185196
186197async fn prepare_mysql_base_url ( ) -> Option < String > {
198+ if let Some ( database_url) = database_url_from_env ( & [ "mysql" ] ) {
199+ let admin_url = replace_database_name ( & database_url, "mysql" ) ;
200+ let mut conn = sqlx:: MySqlConnection :: connect ( & admin_url)
201+ . await
202+ . unwrap_or_else ( |err| {
203+ panic ! ( "DATABASE_URL points to MySQL but connecting to {admin_url} failed: {err:#}" )
204+ } ) ;
205+ conn. execute ( "SELECT 1" ) . await . unwrap_or_else ( |err| {
206+ panic ! ( "DATABASE_URL points to MySQL but validation failed: {err:#}" )
207+ } ) ;
208+ return Some ( replace_database_name ( & database_url, "sqlpage_examples" ) ) ;
209+ }
210+
187211 let mut conn = sqlx:: MySqlConnection :: connect ( "mysql://root:Password123!@localhost/mysql" )
188212 . await
189213 . ok ( ) ?;
@@ -195,11 +219,9 @@ async fn prepare_database(database_url: &str, backend: Backend) {
195219 match backend {
196220 Backend :: Sqlite => { }
197221 Backend :: Postgres => {
198- let db_name = database_url. rsplit ( '/' ) . next ( ) . unwrap ( ) ;
199- let mut conn =
200- sqlx:: PgConnection :: connect ( "postgres://root:Password123!@localhost/postgres" )
201- . await
202- . unwrap ( ) ;
222+ let db_name = database_name ( database_url) ;
223+ let admin_url = replace_database_name ( database_url, "postgres" ) ;
224+ let mut conn = sqlx:: PgConnection :: connect ( & admin_url) . await . unwrap ( ) ;
203225 let _ = conn
204226 . execute ( format ! ( "DROP DATABASE IF EXISTS {db_name} WITH (FORCE)" ) . as_str ( ) )
205227 . await ;
@@ -209,11 +231,9 @@ async fn prepare_database(database_url: &str, backend: Backend) {
209231 tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
210232 }
211233 Backend :: MySql => {
212- let db_name = database_url. rsplit ( '/' ) . next ( ) . unwrap ( ) ;
213- let mut conn =
214- sqlx:: MySqlConnection :: connect ( "mysql://root:Password123!@localhost/mysql" )
215- . await
216- . unwrap ( ) ;
234+ let db_name = database_name ( database_url) ;
235+ let admin_url = replace_database_name ( database_url, "mysql" ) ;
236+ let mut conn = sqlx:: MySqlConnection :: connect ( & admin_url) . await . unwrap ( ) ;
217237 conn. execute ( format ! ( "DROP DATABASE IF EXISTS {db_name}" ) . as_str ( ) )
218238 . await
219239 . unwrap ( ) ;
@@ -225,6 +245,40 @@ async fn prepare_database(database_url: &str, backend: Backend) {
225245 }
226246}
227247
248+ fn database_url_from_env ( schemes : & [ & str ] ) -> Option < String > {
249+ let database_url = std:: env:: var ( "DATABASE_URL" ) . ok ( ) ?;
250+ let scheme = database_url. split_once ( ':' ) ?. 0 ;
251+ schemes. contains ( & scheme) . then_some ( database_url)
252+ }
253+
254+ fn database_name ( database_url : & str ) -> & str {
255+ let url_without_query = database_url
256+ . split_once ( '?' )
257+ . map_or ( database_url, |( url, _query) | url) ;
258+ let database_start = url_without_query
259+ . rfind ( '/' )
260+ . unwrap_or_else ( || panic ! ( "database URL has no path: {database_url}" ) ) ;
261+ & url_without_query[ database_start + 1 ..]
262+ }
263+
264+ fn replace_database_name ( database_url : & str , database_name : & str ) -> String {
265+ let ( url_without_query, query) = database_url
266+ . split_once ( '?' )
267+ . map_or ( ( database_url, "" ) , |( url, query) | ( url, query) ) ;
268+ let database_start = url_without_query
269+ . rfind ( '/' )
270+ . unwrap_or_else ( || panic ! ( "database URL has no path: {database_url}" ) ) ;
271+ let query = if query. is_empty ( ) {
272+ String :: new ( )
273+ } else {
274+ format ! ( "?{query}" )
275+ } ;
276+ format ! (
277+ "{}{database_name}{query}" ,
278+ & url_without_query[ ..=database_start]
279+ )
280+ }
281+
228282fn slug ( name : & str ) -> String {
229283 name. chars ( )
230284 . filter ( |c| c. is_ascii_alphanumeric ( ) )
0 commit comments