@@ -3,14 +3,13 @@ package dataset
33import (
44 "database/sql"
55 "encoding/json"
6+ "errors"
7+ "fmt"
68 "gocldf/csvw/table"
7- "gocldf/db"
89 "os"
910 "path/filepath"
1011 "slices"
1112 "strings"
12-
13- _ "github.com/mattn/go-sqlite3"
1413)
1514
1615type Dataset struct {
@@ -19,16 +18,16 @@ type Dataset struct {
1918 Tables map [string ]* table.Table
2019}
2120
22- func New (md_path string ) * Dataset {
21+ func New (md_path string ) ( * Dataset , error ) {
2322 data , err := os .ReadFile (md_path )
2423 if err != nil {
25- panic ( err )
24+ return nil , err
2625 }
2726 var result map [string ]interface {}
2827
2928 err = json .Unmarshal (data , & result )
3029 if err != nil {
31- panic ( err )
30+ return nil , err
3231 }
3332
3433 metadata := make (map [string ]interface {}, len (result )- 1 )
@@ -44,24 +43,28 @@ func New(md_path string) *Dataset {
4443 metadata ,
4544 make (map [string ]* table.Table )}
4645 for _ , value := range result ["tables" ].([]interface {}) {
47- tbl := table .New (value .(map [string ]interface {}))
46+ tbl , err := table .New (value .(map [string ]interface {}))
47+ if err != nil {
48+ return nil , err
49+ }
4850 res .Tables [tbl .CanonicalName ] = tbl
4951 }
50- return & res
52+ return & res , nil
5153}
5254
53- func (dataset * Dataset ) LoadData () {
55+ func (dataset * Dataset ) LoadData () error {
5456 results := make (chan table.TableRead , len (dataset .Tables ))
5557 for _ , tbl := range dataset .Tables {
5658 go tbl .Read (filepath .Dir (dataset .MetadataPath ), results )
5759 }
5860 for i := 0 ; i < len (dataset .Tables ); i ++ {
5961 tableRead := <- results
6062 if tableRead .Err != nil {
61- panic ( tableRead .Err )
63+ return tableRead .Err
6264 }
6365 }
6466 close (results )
67+ return nil
6568}
6669
6770func (dataset * Dataset ) UrlToTable () map [string ]* table.Table {
@@ -80,29 +83,7 @@ func (dataset *Dataset) UrlToCanonicalName() map[string]string {
8083 return res
8184}
8285
83- func (dataset * Dataset ) SqlSchema () string {
84- var (
85- res []string
86- orderedTables = dataset .OrderedTables ()
87- urlToName = dataset .UrlToCanonicalName ()
88- urlToTable = dataset .UrlToTable ()
89- )
90- for _ , url := range orderedTables {
91- tbl , ok := dataset.Tables [urlToName [url ]]
92- if ok {
93- res = append (res , tbl .SqlCreate (urlToTable ))
94- }
95- }
96- for _ , url := range orderedTables {
97- tbl , ok := dataset.Tables [urlToName [url ]]
98- if ok {
99- res = append (res , tbl .SqlCreateAssociationTables (urlToTable ))
100- }
101- }
102- return strings .Join (res , "\n " )
103- }
104-
105- func (dataset * Dataset ) OrderedTables () []string {
86+ func (dataset * Dataset ) orderedTables () (map [string ]* table.Table , error ) {
10687 var urlToName = dataset .UrlToCanonicalName ()
10788 // Determine the order in which to create the tables
10889 tables := []string {}
@@ -114,7 +95,7 @@ func (dataset *Dataset) OrderedTables() []string {
11495 for len (tables ) > 0 {
11596 j ++
11697 if j > 100 {
117- panic ("there may be cyclic dependencies between tables" )
98+ return nil , errors . New ("there may be cyclic dependencies between tables" )
11899 }
119100 // We loop over all tables that have not been ordered yet, trying to find one with
120101 // only fks to already ordered tables.
@@ -138,45 +119,86 @@ func (dataset *Dataset) OrderedTables() []string {
138119 break
139120 }
140121 } else {
141- panic ("table not found" )
122+ return nil , errors . New ("table not found" )
142123 }
143124 }
144125 if delIndex >= 0 {
145126 tables = slices .Delete (tables , delIndex , delIndex + 1 )
146127 }
147128 }
148- return orderedTables
129+ orderedTableMap := make (map [string ]* table.Table , len (orderedTables ))
130+ for _ , url := range orderedTables {
131+ tbl , ok := dataset.Tables [urlToName [url ]]
132+ if ok {
133+ orderedTableMap [url ] = tbl
134+ } else {
135+ return orderedTableMap , fmt .Errorf ("table %s not found" , url )
136+ }
137+ }
138+ return orderedTableMap , nil
149139}
150140
151- func (dataset * Dataset ) ToSqlite (db_path string ) {
152- err := db .WithDatabase (db_path , func (database * sql.DB ) error {
153- _ , err := database .Exec (dataset .SqlSchema ())
141+ func (dataset * Dataset ) sqlSchema () (string , error ) {
142+ var (
143+ res []string
144+ urlToTable = dataset .UrlToTable ()
145+ )
146+ orderedTableMap , err := dataset .orderedTables ()
147+ if err != nil {
148+ return "" , err
149+ }
150+
151+ for _ , tbl := range orderedTableMap {
152+ schema , err := tbl .SqlCreate (urlToTable )
154153 if err != nil {
155- return err
154+ return "" , err
155+ } else {
156+ res = append (res , schema )
157+ }
158+ }
159+ for _ , tbl := range orderedTableMap {
160+ for _ , fk := range tbl .ManyToMany () {
161+ res = append (res , tbl .SqlCreateAssociationTable (* fk , urlToTable ))
156162 }
163+ }
164+ return strings .Join (res , "\n " ), nil
165+ }
157166
158- orderedTables := dataset .OrderedTables ()
159- urlToName := dataset .UrlToCanonicalName ()
160- urlToTable := dataset .UrlToTable ()
167+ type TableData struct {
168+ TableName string
169+ ColNames []string
170+ Rows [][]any
171+ }
161172
162- db .WithTransaction (database , func (tx * sql.Tx ) {
163- for _ , url := range orderedTables {
164- tbl , ok := dataset.Tables [urlToName [url ]]
165- if ok {
166- tbl .SqlInsert (tx )
167- }
168- }
173+ // Function ToSqlite returns the data necessary to load the dataset into a SQLite database.
174+ func (dataset * Dataset ) ToSqlite (tx * sql.Tx ) (string , []TableData , error ) {
175+ var tableData = []TableData {}
169176
170- for _ , url := range orderedTables {
171- tbl , ok := dataset.Tables [urlToName [url ]]
172- if ok {
173- tbl .SqlInsertAssociationTables (tx , urlToTable )
174- }
175- }
176- })
177- return err
178- }, true )
177+ schema , err := dataset .sqlSchema ()
178+ if err != nil {
179+ return "" , tableData , err
180+ }
181+ orderedTables , err := dataset .orderedTables ()
179182 if err != nil {
180- return
183+ return "" , tableData , err
184+ }
185+ urlToTable := dataset .UrlToTable ()
186+
187+ for _ , tbl := range orderedTables {
188+ rows , colNames , err := tbl .RowsToSql ()
189+ if err != nil {
190+ return "" , tableData , err
191+ }
192+ tableData = append (tableData , TableData {tbl .CanonicalName , colNames , rows })
193+ }
194+ for _ , tbl := range orderedTables {
195+ for _ , fk := range tbl .ManyToMany () {
196+ rows , tableName , colNames , err := tbl .AssociationTableRowsToSql (fk , urlToTable )
197+ if err != nil {
198+ return "" , tableData , err
199+ }
200+ tableData = append (tableData , TableData {tableName , colNames , rows })
201+ }
181202 }
203+ return schema , tableData , nil
182204}
0 commit comments