Skip to content

Commit e6bc911

Browse files
committed
Updated sqlimport
1 parent 6489f55 commit e6bc911

File tree

17 files changed

+1429
-124
lines changed

17 files changed

+1429
-124
lines changed

cmd/sqtool/main.go

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package main
22

33
import (
4+
"C"
45
"flag"
56
"fmt"
67
"io"
78
"log"
89
"os"
910
"path/filepath"
1011
"time"
12+
"unsafe"
1113

1214
// Modules
1315
importer "github.com/djthorpe/go-sqlite/pkg/importer"
@@ -16,6 +18,10 @@ import (
1618
// Namespace Imports
1719
. "github.com/djthorpe/go-sqlite"
1820
)
21+
import (
22+
"errors"
23+
"math"
24+
)
1925

2026
var (
2127
flagOverwrite = flag.Bool("overwrite", false, "Overwrite existing tables")
@@ -49,6 +55,8 @@ func main() {
4955
}
5056
defer db.Close()
5157

58+
db.SetTraceHook(trace, sqlite3.SQLITE_TRACE_PROFILE)
59+
5260
// Report on the database
5361
log.Println("database:", db.Filename(sqlite3.DefaultSchema))
5462

@@ -75,52 +83,44 @@ func main() {
7583
// Read files
7684
for _, url := range flag.Args()[1:] {
7785
// Create an importer
78-
importer, err := importer.NewImporter(config, url)
86+
importer, err := importer.NewImporter(config, url, writer)
7987
if err != nil {
8088
fmt.Fprintln(os.Stderr, importer.URL(), ": ", err)
8189
continue
8290
}
8391

84-
// Create the decoder
92+
// Create the decoder, guess mimetype instead of supplying it
8593
decoder, err := importer.Decoder("")
8694
if err != nil {
8795
fmt.Fprintln(os.Stderr, importer.URL(), ": ", err)
8896
continue
8997
}
90-
defer decoder.Close()
9198

9299
// Reset the counter
93100
log.Println(" import:", importer.URL())
94101
log.Println(" ...decoder", decoder)
95102

96-
// Call Begin for writer to get writing function
97-
fn, err := writer.Begin(importer.Name(), sqlite3.DefaultSchema, []string{"continent"})
98-
if err != nil {
99-
fmt.Fprintln(os.Stderr, importer.URL(), ": ", err)
100-
continue
101-
}
102-
103103
// Read and write rows
104104
start, mark := time.Now(), time.Now()
105105
for {
106-
if err := importer.ReadWrite(decoder, fn); err == io.EOF {
107-
writer.End(true) // commit
106+
if err := importer.ReadWrite(decoder); err == io.EOF {
107+
break
108+
} else if errors.Is(err, io.EOF) {
108109
break
109110
} else if err != nil {
110-
writer.End(false) // rollback
111111
fmt.Fprintln(os.Stderr, importer.URL(), ": ", err)
112112
break
113113
}
114114
if time.Since(mark) > 5*time.Second {
115-
log.Printf(" ...written %d rows", 0)
115+
log.Printf(" ...written %d rows", writer.Count())
116116
mark = time.Now()
117117
}
118118
}
119119

120120
// Report
121121
since := time.Since(start)
122-
//ops_per_sec := math.Round(float64(writer.Count()) * 1000 / float64(since.Milliseconds()))
123-
log.Printf(" ...written %d rows in %v (%.0f ops/s)", 0, since.Truncate(time.Millisecond), 0)
122+
ops_per_sec := math.Round(float64(writer.Count()) * 1000 / float64(since.Milliseconds()))
123+
log.Printf(" ...written %d rows in %v (%.0f ops/s)", writer.Count(), since.Truncate(time.Millisecond), ops_per_sec)
124124
}
125125
}
126126

@@ -131,3 +131,17 @@ func logger(name string) *log.Logger {
131131
return log.New(os.Stderr, name, 0)
132132
}
133133
}
134+
func trace(t sqlite3.TraceType, a, b unsafe.Pointer) int {
135+
switch t {
136+
case sqlite3.SQLITE_TRACE_STMT:
137+
fmt.Println("STMT => ", (*sqlite3.Statement)(a), C.GoString((*C.char)(b)))
138+
case sqlite3.SQLITE_TRACE_PROFILE:
139+
ms := time.Duration(time.Duration(*(*int64)(b)) * time.Nanosecond)
140+
fmt.Println("PROF => ", (*sqlite3.Statement)(a), ms)
141+
case sqlite3.SQLITE_TRACE_ROW:
142+
fmt.Println("ROW => ", (*sqlite3.Statement)(a))
143+
case sqlite3.SQLITE_TRACE_CLOSE:
144+
fmt.Println("CLSE => ", (*sqlite3.Conn)(a))
145+
}
146+
return 0
147+
}

go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,12 @@ require (
1515

1616
require (
1717
github.com/hashicorp/errwrap v1.1.0 // indirect
18+
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
19+
github.com/richardlehane/mscfb v1.0.3 // indirect
20+
github.com/richardlehane/msoleps v1.0.1 // indirect
21+
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 // indirect
22+
github.com/xuri/excelize/v2 v2.4.1 // indirect
23+
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
24+
golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect
1825
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
1926
)

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,33 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9
2121
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
2222
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
2323
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
24+
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
25+
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
2426
github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
2527
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
28+
github.com/richardlehane/mscfb v1.0.3 h1:rD8TBkYWkObWO0oLDFCbwMeZ4KoalxQy+QgniCj3nKI=
29+
github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
30+
github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o=
31+
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
2632
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
2733
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
2834
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
35+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
2936
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
37+
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 h1:EpI0bqf/eX9SdZDwlMmahKM+CDBgNbsXMhsN28XrM8o=
38+
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
39+
github.com/xuri/excelize/v2 v2.4.1 h1:veeeFLAJwsNEBPBlDepzPIYS1eLyBVcXNZUW79exZ1E=
40+
github.com/xuri/excelize/v2 v2.4.1/go.mod h1:rSu0C3papjzxQA3sdK8cU544TebhrPUoTOaGPIh0Q1A=
3041
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
3142
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
43+
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
44+
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
3245
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
46+
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
3347
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
3448
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
49+
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
50+
golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw=
3551
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
3652
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
3753
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

npm/sqlite3/html/index.html

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<meta name="description" content="sqlite api">
99
<link rel="icon" href="/assets/favicon/favicon.ico">
1010
<link rel="stylesheet" href="/index.css" media="all">
11-
<script src="/index.js"></script>
11+
<script src="/index.js" defer></script>
1212
</head>
1313

1414
<body>
@@ -30,11 +30,11 @@
3030
</div>
3131
</div>
3232
<!-- LEFT/RIGHT NAVIGATION -->
33-
<div class="container-fluid">
34-
<div class="row">
35-
<div class="col-md-10 mt-1" id="schema">
33+
<div class="container-fluid p-0">
34+
<div class="row m-0">
35+
<div class="col-md-10 p-0" id="schema">
3636
<!-- BODY CONTENT (SchemaView) -->
37-
<div class="_title bg-light rounded p-2 mb-2">
37+
<div class="_title bg-light border-bottom p-2">
3838
<h1 class="_name">[schema]</h1>
3939
<small class="_filename">[filename]</small>
4040
</div>
@@ -45,24 +45,7 @@ <h1 class="_name">[schema]</h1>
4545
</ul>
4646
<!-- TABLE CONTENT (TableView) -->
4747
<div class="m-2">
48-
<table class="table table-hover table-sm table-striped" id="schema-table-data">
49-
<thead>
50-
<tr>
51-
<th>[col]</th>
52-
</tr>
53-
</thead>
54-
<tbody>
55-
<tr>
56-
<td>[row]</td>
57-
</tr>
58-
<tr>
59-
<td>[row]</td>
60-
</tr>
61-
<tr>
62-
<td>[row]</td>
63-
</tr>
64-
</tbody>
65-
</table>
48+
<table-view id="results" data-class="table-hover table-sm table-striped" data-columns="Col A, Col B, Col D" data-rows="4"></table-view>
6649
</div>
6750
</div>
6851
<div class="col-md-2 d-md-block d-none bg-light border-start" id="database">

npm/sqlite3/js/index.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ import '../css/index.css';
55
// Application Controllers
66
import App from './controller/app';
77

8+
// Views
9+
import ComponentView from './view/component-view';
10+
import BadgeView from './view/badge-view';
11+
import TableView from './view/table-view';
12+
import TableHeadView from './view/table-head-view';
13+
import TableBodyView from './view/table-body-view';
14+
15+
// Define tag names
16+
ComponentView.define('badge-view', BadgeView);
17+
ComponentView.define('table-view', TableView);
18+
ComponentView.define('table-head-view', TableHeadView);
19+
ComponentView.define('table-body-view', TableBodyView);
20+
821
// Import js-framework
922
const jsf = require('@djthorpe/js-framework');
1023

pkg/importer/csvdecoder.go

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package sqimport
1+
package importer
22

33
import (
44
"encoding/csv"
@@ -17,14 +17,15 @@ type csvdecoder struct {
1717
r *csv.Reader
1818
header bool
1919
cols []string
20+
values []interface{}
2021
}
2122

2223
///////////////////////////////////////////////////////////////////////////////
2324
// LIFECYCLE
2425

2526
// NewCSVDecoder returns a CSV decoder setting options
2627
func (this *Importer) NewCSVDecoder(c io.Closer, r io.Reader, delimiter rune) (SQImportDecoder, error) {
27-
decoder := &csvdecoder{c, csv.NewReader(r), this.c.Header, nil}
28+
decoder := &csvdecoder{c, csv.NewReader(r), this.c.Header, nil, nil}
2829

2930
// Set delimiter
3031
if this.c.Delimiter != 0 {
@@ -61,11 +62,11 @@ func (dec *csvdecoder) String() string {
6162

6263
// Read reads a CSV record, and returns io.EOF on end of reading.
6364
// May return nil for values to skip a write.
64-
func (this *csvdecoder) Read() (map[string]interface{}, error) {
65+
func (this *csvdecoder) Read() ([]string, []interface{}, error) {
6566
// Read a row
6667
row, err := this.r.Read()
6768
if err != nil {
68-
return nil, err
69+
return nil, nil, err
6970
}
7071

7172
// Initialize the reader
@@ -79,17 +80,23 @@ func (this *csvdecoder) Read() (map[string]interface{}, error) {
7980
}
8081
}
8182
if this.header {
82-
return nil, nil
83+
return nil, nil, nil
8384
}
8485
}
8586

86-
// Add new column headings as necessary
87+
// Add new column headings as necessary, populate values
8788
for len(row) > len(this.cols) {
8889
this.cols = append(this.cols, this.makeCol(len(this.cols)))
8990
}
91+
if len(this.values) != len(row) {
92+
this.values = make([]interface{}, len(this.cols))
93+
}
94+
for i, v := range row {
95+
this.values[i] = v
96+
}
9097

91-
// Zip and return
92-
return zip(this.cols[:len(row)], row), nil
98+
// Return
99+
return this.cols, this.values, nil
93100
}
94101

95102
////////////////////////////////////////////////////////////////////////////////
@@ -99,15 +106,3 @@ func (this *csvdecoder) Read() (map[string]interface{}, error) {
99106
func (this *csvdecoder) makeCol(i int) string {
100107
return fmt.Sprintf("col_%02d", i)
101108
}
102-
103-
// Return row as map[string]interface{}
104-
func zip(k, v []string) map[string]interface{} {
105-
if len(k) != len(v) {
106-
return nil
107-
}
108-
result := make(map[string]interface{}, len(v))
109-
for i, v := range v {
110-
result[k[i]] = v
111-
}
112-
return result
113-
}

pkg/importer/decoder.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package sqimport
1+
package importer
22

33
import (
44
"fmt"
@@ -44,6 +44,16 @@ func (this *Importer) Decoder(mimetype string) (SQImportDecoder, error) {
4444
// Set decoder based on mediatype and other possible
4545
// parameters
4646
switch {
47+
case mediatype == "application/vnd.ms-excel":
48+
return this.NewXLSDecoder(r)
49+
case mediatype == "application/excel":
50+
return this.NewXLSDecoder(r)
51+
case mediatype == "application/x-excel":
52+
return this.NewXLSDecoder(r)
53+
case mediatype == "application/x-msexcel":
54+
return this.NewXLSDecoder(r)
55+
case mediatype == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
56+
return this.NewXLSDecoder(r)
4757
case mediatype == "text/csv":
4858
return this.NewCSVDecoder(r, cr, ',')
4959
case mediatype == "text/tsv":

0 commit comments

Comments
 (0)