Skip to content

Commit f081169

Browse files
authored
dev: first release ever (#1)
1 parent 1bd2832 commit f081169

File tree

8 files changed

+198
-2
lines changed

8 files changed

+198
-2
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@
2121
# Go workspace file
2222
go.work
2323

24+
/test.db
25+
/tests/test.db

Diff for: Makefile

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
get::
2+
# go get -modfile=go_test.mod
3+
go get -modfile=go.mod
4+
# cp go_test.sum go.sum
5+
6+
7+
tests::
8+
rm -rf test.db
9+
sqlite3 -batch test.db ""
10+
#go test -v ./...
11+
go test -modfile=go_test.mod ./... -v

Diff for: README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ for rows.Next() {
1313
rec := Rows2Map(rows)
1414
data = append(data, rec)
1515
}
16-
1716
```
1817

18+
check also [go_sql_raw_test.go](go_sql_raw_test.go)
19+
1920
## TODO
20-
* ...
21+
* type converting from DB to go in function `update`
22+
23+
## Credits
24+
* module inspired by https://gist.github.com/SchumacherFM/69a167bec7dea644a20e

Diff for: go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
module github.com/mysiar-org/go-sql-raw
22

33
go 1.22.2
4+

Diff for: go_sql_raw.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package go_sql_raw
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
"log"
7+
"strconv"
8+
)
9+
10+
type RawSqlType map[string]interface{}
11+
12+
func Error(err error) {
13+
if err != nil {
14+
log.Fatal(err)
15+
}
16+
}
17+
18+
func Rows2Map(rows *sql.Rows) RawSqlType {
19+
columns, err := rows.Columns()
20+
columnTypes, err := rows.ColumnTypes()
21+
Error(err)
22+
rc := newMapRawSqlScan(columns, columnTypes)
23+
err = rc.update(rows)
24+
Error(err)
25+
return rc.get()
26+
}
27+
28+
type mapRawSqlScan struct {
29+
cp []interface{}
30+
row RawSqlType
31+
colCount int
32+
colNames []string
33+
colTypes []*sql.ColumnType
34+
}
35+
36+
func (s *mapRawSqlScan) update(rows *sql.Rows) error {
37+
if err := rows.Scan(s.cp...); err != nil {
38+
return err
39+
}
40+
41+
for i := 0; i < s.colCount; i++ {
42+
if rb, ok := s.cp[i].(*sql.RawBytes); ok {
43+
val := string(*rb)
44+
var parsed any
45+
switch s.colTypes[i].DatabaseTypeName() {
46+
case "DECIMAL":
47+
parsed, _ = strconv.ParseFloat(val, 64)
48+
case "INT":
49+
parsed, _ = strconv.ParseInt(val, 10, 64)
50+
default:
51+
parsed = val
52+
}
53+
s.row[s.colNames[i]] = parsed
54+
*rb = nil
55+
} else {
56+
return fmt.Errorf("Cannot convert index %d column %s to type *sql.RawBytes", i, s.colNames[i])
57+
}
58+
}
59+
60+
return nil
61+
}
62+
63+
func (s *mapRawSqlScan) get() RawSqlType {
64+
return s.row
65+
}
66+
67+
func newMapRawSqlScan(columnNames []string, columnTypes []*sql.ColumnType) *mapRawSqlScan {
68+
lenCN := len(columnNames)
69+
s := &mapRawSqlScan{
70+
cp: make([]interface{}, lenCN),
71+
row: make(RawSqlType, lenCN),
72+
colCount: lenCN,
73+
colNames: columnNames,
74+
colTypes: columnTypes,
75+
}
76+
for i := 0; i < lenCN; i++ {
77+
s.cp[i] = new(sql.RawBytes)
78+
}
79+
return s
80+
}

Diff for: go_test.mod

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module github.com/mysiar-org/go-sql-raw
2+
3+
go 1.22.2
4+
5+
require (
6+
github.com/mattn/go-sqlite3 v1.14.22
7+
github.com/stretchr/testify v1.9.0
8+
)
9+
10+
require (
11+
github.com/davecgh/go-spew v1.1.1 // indirect
12+
github.com/pmezard/go-difflib v1.0.0 // indirect
13+
gopkg.in/yaml.v3 v3.0.1 // indirect
14+
)

Diff for: go_test.sum

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
4+
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
8+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
10+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
11+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
12+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

Diff for: tests/go_sql_raw_test.go

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package tests
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
_ "github.com/mattn/go-sqlite3"
7+
"github.com/mysiar-org/go-sql-raw"
8+
"github.com/stretchr/testify/assert"
9+
"strconv"
10+
"testing"
11+
)
12+
13+
func Test(t *testing.T) {
14+
const file string = "test.db"
15+
db, err := sql.Open("sqlite3", file)
16+
chkError(err)
17+
_, err = db.Exec(dropTable())
18+
chkError(err)
19+
_, err = db.Exec(createTable())
20+
chkError(err)
21+
_, err = db.Exec(insertData())
22+
chkError(err)
23+
24+
var rows *sql.Rows
25+
rows, err = db.Query("SELECT * FROM album ORDER BY id")
26+
27+
var data []go_sql_raw.RawSqlType
28+
for rows.Next() {
29+
rec := go_sql_raw.Rows2Map(rows)
30+
data = append(data, rec)
31+
}
32+
33+
var expectedIds = []int64{1, 2, 3, 4, 5}
34+
var expectedPrices = []float64{56.99, 63.99, 17.99, 34.98, 80.99}
35+
var expectedArtists = []string{"John Coltrane", "John Coltrane", "Gerry Mulligan", "Sarah Vaughan", "Schizma"}
36+
var expectedTitle = []string{"Blue Train", "Giant Steps", "Jeru", "Sarah Vaughan", "Upadek"}
37+
38+
for idx, entry := range data {
39+
id, _ := strconv.ParseInt(fmt.Sprintf("%v", entry["id"]), 10, 64)
40+
assert.Equal(t, expectedIds[idx], id)
41+
price, _ := strconv.ParseFloat(fmt.Sprintf("%v", entry["price"]), 64)
42+
assert.Equal(t, expectedPrices[idx], price)
43+
assert.Equal(t, expectedArtists[idx], entry["artist"])
44+
assert.Equal(t, expectedTitle[idx], entry["title"])
45+
}
46+
}
47+
48+
func dropTable() string {
49+
return "DROP TABLE IF EXISTS album"
50+
}
51+
52+
func createTable() string {
53+
return "CREATE TABLE album (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(128) NOT NULL, artist VARCHAR(255) NOT NULL, price DECIMAL(5,2) NOT NULL, PRIMARY KEY (`id`))"
54+
}
55+
56+
func insertData() string {
57+
return `
58+
INSERT INTO album (id, title, artist, price)
59+
VALUES
60+
(1, 'Blue Train', 'John Coltrane', 56.99),
61+
(2, 'Giant Steps', 'John Coltrane', 63.99),
62+
(3, 'Jeru', 'Gerry Mulligan', 17.99),
63+
(4, 'Sarah Vaughan', 'Sarah Vaughan', 34.98),
64+
(5, 'Upadek', 'Schizma', 80.99)
65+
`
66+
}
67+
68+
func chkError(err error) {
69+
if err != nil {
70+
fmt.Println(err)
71+
}
72+
}

0 commit comments

Comments
 (0)