@@ -66,6 +66,33 @@ function generateSchema(): AnySchema {
6666 return generatedSchema ;
6767}
6868
69+ /**
70+ * Split SQL content into individual statements for Turso compatibility
71+ */
72+ function splitSQLStatements ( sqlContent : string ) : string [ ] {
73+ // First split by the statement breakpoint marker
74+ const sections = sqlContent . split ( '--> statement-breakpoint' ) ;
75+ const statements : string [ ] = [ ] ;
76+
77+ for ( const section of sections ) {
78+ const trimmed = section . trim ( ) ;
79+ if ( ! trimmed ) continue ;
80+
81+ // Further split by semicolons to ensure each statement is separate
82+ // This handles cases where multiple statements aren't separated by breakpoints
83+ const subStatements = trimmed . split ( ';' ) ;
84+
85+ for ( const subStatement of subStatements ) {
86+ const cleanStatement = subStatement . trim ( ) ;
87+ if ( cleanStatement ) {
88+ // Add semicolon back if it was removed by split
89+ statements . push ( cleanStatement + ';' ) ;
90+ }
91+ }
92+ }
93+
94+ return statements ;
95+ }
6996
7097/**
7198 * Create database instance based on configuration
@@ -200,18 +227,8 @@ async function applyMigrations(db: AnyDatabase, config: DatabaseConfig, logger:
200227 // SQLite uses the better-sqlite3 client
201228 ( db as any ) . $client . exec ( createTableQuery ) ;
202229 } else if ( config . type === 'turso' ) {
203- // Turso uses libSQL client - try different approaches
204- if ( ( db as any ) . $client && typeof ( db as any ) . $client . execute === 'function' ) {
205- // Use execute method for libSQL
206- await ( db as any ) . $client . execute ( createTableQuery ) ;
207- } else if ( ( db as any ) . $client && typeof ( db as any ) . $client . prepare === 'function' ) {
208- // Use prepare/run for libSQL
209- const prepared = ( db as any ) . $client . prepare ( createTableQuery ) ;
210- await prepared . run ( ) ;
211- } else {
212- // Fallback: use Drizzle's run method
213- await db . run ( createTableQuery ) ;
214- }
230+ // Turso uses libSQL client - execute single statement
231+ await ( db as any ) . $client . execute ( createTableQuery . trim ( ) ) ;
215232 }
216233
217234 if ( ! isTestMode ( ) ) {
@@ -240,18 +257,8 @@ async function applyMigrations(db: AnyDatabase, config: DatabaseConfig, logger:
240257 appliedMigrations = ( db as any ) . $client . prepare ( selectAppliedQuery ) . all ( ) ;
241258 } else if ( config . type === 'turso' ) {
242259 // Turso uses libSQL client
243- if ( ( db as any ) . $client && typeof ( db as any ) . $client . execute === 'function' ) {
244- const result = await ( db as any ) . $client . execute ( selectAppliedQuery ) ;
245- appliedMigrations = result . rows || [ ] ;
246- } else if ( ( db as any ) . $client && typeof ( db as any ) . $client . prepare === 'function' ) {
247- const prepared = ( db as any ) . $client . prepare ( selectAppliedQuery ) ;
248- const result = await prepared . all ( ) ;
249- appliedMigrations = result || [ ] ;
250- } else {
251- // Fallback: use Drizzle's all method
252- const result = await db . all ( selectAppliedQuery ) ;
253- appliedMigrations = result || [ ] ;
254- }
260+ const result = await ( db as any ) . $client . execute ( selectAppliedQuery ) ;
261+ appliedMigrations = result . rows || [ ] ;
255262 }
256263
257264 if ( ! isTestMode ( ) ) {
@@ -294,44 +301,70 @@ async function applyMigrations(db: AnyDatabase, config: DatabaseConfig, logger:
294301 }
295302 const migrationFilePath = path . join ( migrationsPath , file ) ;
296303 const sqlContent = await fs . readFile ( migrationFilePath , 'utf8' ) ;
297- const statements = sqlContent . split ( '--> statement-breakpoint' ) ;
304+
305+ // Use improved statement splitting for Turso
306+ const statements = config . type === 'turso'
307+ ? splitSQLStatements ( sqlContent )
308+ : sqlContent . split ( '--> statement-breakpoint' ) ;
298309
299310 try {
311+ let statementCount = 0 ;
300312 for ( const statement of statements ) {
301313 const trimmedStatement = statement . trim ( ) ;
302314 if ( trimmedStatement ) {
315+ statementCount ++ ;
303316 if ( config . type === 'sqlite' ) {
304317 ( db as any ) . $client . exec ( trimmedStatement ) ;
305318 } else if ( config . type === 'turso' ) {
306- // Turso uses libSQL client
307- if ( ( db as any ) . $client && typeof ( db as any ) . $client . execute === 'function' ) {
319+ // Log each statement for debugging
320+ if ( ! isTestMode ( ) ) {
321+ logger . debug ( {
322+ operation : 'apply_migrations' ,
323+ migrationFile : file ,
324+ statementNumber : statementCount ,
325+ statementPreview : trimmedStatement . substring ( 0 , 100 ) + ( trimmedStatement . length > 100 ? '...' : '' ) ,
326+ databaseType : config . type
327+ } , `Executing statement ${ statementCount } ` ) ;
328+ }
329+
330+ // Turso - execute each statement individually
331+ try {
308332 await ( db as any ) . $client . execute ( trimmedStatement ) ;
309- } else if ( ( db as any ) . $client && typeof ( db as any ) . $client . prepare === 'function' ) {
310- const prepared = ( db as any ) . $client . prepare ( trimmedStatement ) ;
311- await prepared . run ( ) ;
312- } else {
313- // Fallback: use Drizzle's run method
314- await db . run ( trimmedStatement ) ;
333+ } catch ( stmtError : any ) {
334+ logger . error ( {
335+ operation : 'apply_migrations' ,
336+ migrationFile : file ,
337+ statementNumber : statementCount ,
338+ statement : trimmedStatement ,
339+ databaseType : config . type ,
340+ error : stmtError ,
341+ errorMessage : stmtError . message
342+ } , `Failed to execute statement ${ statementCount } ` ) ;
343+ throw stmtError ;
315344 }
316345 }
317346 }
318347 }
319348
349+ if ( ! isTestMode ( ) ) {
350+ logger . info ( {
351+ operation : 'apply_migrations' ,
352+ migrationFile : file ,
353+ statementCount,
354+ databaseType : config . type
355+ } , `Successfully executed ${ statementCount } statements from migration` ) ;
356+ }
357+
320358 // Record the migration as applied
321359 const insertMigrationQuery = `INSERT INTO ${ MIGRATIONS_TABLE_NAME } (migration_name) VALUES (?)` ;
322360 if ( config . type === 'sqlite' ) {
323361 ( db as any ) . $client . prepare ( insertMigrationQuery ) . run ( file ) ;
324362 } else if ( config . type === 'turso' ) {
325- // Turso uses libSQL client
326- if ( ( db as any ) . $client && typeof ( db as any ) . $client . execute === 'function' ) {
327- await ( db as any ) . $client . execute ( insertMigrationQuery , [ file ] ) ;
328- } else if ( ( db as any ) . $client && typeof ( db as any ) . $client . prepare === 'function' ) {
329- const prepared = ( db as any ) . $client . prepare ( insertMigrationQuery ) ;
330- await prepared . run ( [ file ] ) ;
331- } else {
332- // Fallback: use Drizzle's run method
333- await db . run ( insertMigrationQuery , [ file ] ) ;
334- }
363+ // Turso uses libSQL client with parameterized query
364+ await ( db as any ) . $client . execute ( {
365+ sql : insertMigrationQuery ,
366+ args : [ file ]
367+ } ) ;
335368 }
336369
337370 if ( ! isTestMode ( ) ) {
0 commit comments