@@ -8,13 +8,11 @@ import (
88 "fmt"
99 "strings"
1010 "time"
11-
12- _ "modernc.org/sqlite"
1311)
1412
1513// Catalog provides SQL querying over Mendix project metadata.
1614type Catalog struct {
17- db * sql. DB
15+ db CatalogDB
1816 projectID string
1917 projectName string
2018 mendixVersion string
@@ -58,17 +56,15 @@ type ProgressFunc func(table string, count int)
5856
5957// New creates a new catalog with an in-memory SQLite database.
6058func New () (* Catalog , error ) {
61- db , err := sql . Open ( "sqlite" , ":memory:" )
59+ db , err := NewSqliteCatalogDB ( )
6260 if err != nil {
6361 return nil , fmt .Errorf ("failed to open in-memory database: %w" , err )
6462 }
63+ return NewFromDB (db )
64+ }
6565
66- // Enable foreign keys
67- if _ , err := db .Exec ("PRAGMA foreign_keys = ON" ); err != nil {
68- db .Close ()
69- return nil , fmt .Errorf ("failed to enable foreign keys: %w" , err )
70- }
71-
66+ // NewFromDB creates a catalog from an existing CatalogDB.
67+ func NewFromDB (db CatalogDB ) (* Catalog , error ) {
7268 c := & Catalog {
7369 db : db ,
7470 projectID : "default" ,
@@ -193,8 +189,8 @@ func (c *Catalog) Query(sqlQuery string) (*QueryResult, error) {
193189 return result , rows .Err ()
194190}
195191
196- // DB returns the underlying database connection for direct access .
197- func (c * Catalog ) DB () * sql. DB {
192+ // CatalogDB returns the underlying database abstraction .
193+ func (c * Catalog ) CatalogDB () CatalogDB {
198194 return c .db
199195}
200196
@@ -263,17 +259,11 @@ type CacheInfo struct {
263259
264260// NewFromFile opens a catalog from a persisted SQLite file.
265261func NewFromFile (path string ) (* Catalog , error ) {
266- db , err := sql . Open ( "sqlite" , path )
262+ db , err := NewSqliteCatalogDBFromFile ( path )
267263 if err != nil {
268264 return nil , fmt .Errorf ("failed to open catalog file: %w" , err )
269265 }
270266
271- // Enable foreign keys
272- if _ , err := db .Exec ("PRAGMA foreign_keys = ON" ); err != nil {
273- db .Close ()
274- return nil , fmt .Errorf ("failed to enable foreign keys: %w" , err )
275- }
276-
277267 c := & Catalog {
278268 db : db ,
279269 projectID : "default" ,
@@ -286,7 +276,14 @@ func NewFromFile(path string) (*Catalog, error) {
286276
287277// SaveToFile saves the catalog to a SQLite file.
288278// This copies the in-memory database to a file for persistence.
279+ // Requires the underlying CatalogDB to be a *SqliteCatalogDB.
289280func (c * Catalog ) SaveToFile (path string ) error {
281+ sdb , ok := c .db .(* SqliteCatalogDB )
282+ if ! ok {
283+ return fmt .Errorf ("SaveToFile requires a SQLite-backed catalog" )
284+ }
285+ rawDB := sdb .RawDB ()
286+
290287 // Open destination file database
291288 destDB , err := sql .Open ("sqlite" , path )
292289 if err != nil {
@@ -296,17 +293,17 @@ func (c *Catalog) SaveToFile(path string) error {
296293
297294 // Use SQLite backup API via VACUUM INTO (SQLite 3.27+)
298295 // Fall back to manual copy if not available
299- _ , err = c . db .Exec (fmt .Sprintf ("VACUUM INTO '%s'" , path ))
296+ _ , err = rawDB .Exec (fmt .Sprintf ("VACUUM INTO '%s'" , path ))
300297 if err != nil {
301298 // Fall back: export and import
302- return c .saveToFileManual (path )
299+ return c .saveToFileManual (path , rawDB )
303300 }
304301
305302 return nil
306303}
307304
308305// saveToFileManual saves by dumping and restoring (fallback method).
309- func (c * Catalog ) saveToFileManual (path string ) error {
306+ func (c * Catalog ) saveToFileManual (path string , rawDB * sql. DB ) error {
310307 // Open destination
311308 destDB , err := sql .Open ("sqlite" , path )
312309 if err != nil {
@@ -315,7 +312,7 @@ func (c *Catalog) saveToFileManual(path string) error {
315312 defer destDB .Close ()
316313
317314 // Get list of tables
318- rows , err := c . db .Query ("SELECT name, sql FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'" )
315+ rows , err := rawDB .Query ("SELECT name, sql FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'" )
319316 if err != nil {
320317 return err
321318 }
@@ -339,7 +336,7 @@ func (c *Catalog) saveToFileManual(path string) error {
339336 }
340337
341338 // Copy data
342- srcRows , err := c . db .Query (fmt .Sprintf ("SELECT * FROM %s" , t .name ))
339+ srcRows , err := rawDB .Query (fmt .Sprintf ("SELECT * FROM %s" , t .name ))
343340 if err != nil {
344341 return err
345342 }
@@ -377,7 +374,7 @@ func (c *Catalog) saveToFileManual(path string) error {
377374 }
378375
379376 // Copy views
380- rows , err = c . db .Query ("SELECT sql FROM sqlite_master WHERE type='view'" )
377+ rows , err = rawDB .Query ("SELECT sql FROM sqlite_master WHERE type='view'" )
381378 if err != nil {
382379 return err
383380 }
@@ -394,7 +391,7 @@ func (c *Catalog) saveToFileManual(path string) error {
394391 rows .Close ()
395392
396393 // Copy indexes
397- rows , err = c . db .Query ("SELECT sql FROM sqlite_master WHERE type='index' AND sql IS NOT NULL" )
394+ rows , err = rawDB .Query ("SELECT sql FROM sqlite_master WHERE type='index' AND sql IS NOT NULL" )
398395 if err != nil {
399396 return err
400397 }
0 commit comments