Skip to content

Commit aae9a37

Browse files
committed
Changing duckdb metadata reader
1 parent 9b525b8 commit aae9a37

File tree

1 file changed

+124
-2
lines changed

1 file changed

+124
-2
lines changed

drivers/duckdb/duckdb.go

+124-2
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,137 @@ package duckdb
55

66
import (
77
"context"
8+
"database/sql"
9+
"fmt"
810
"io"
11+
"strings"
912

1013
_ "github.com/marcboeker/go-duckdb" // DRIVER
1114
"github.com/xo/usql/drivers"
1215
"github.com/xo/usql/drivers/metadata"
16+
infos "github.com/xo/usql/drivers/metadata/informationschema"
1317
mymeta "github.com/xo/usql/drivers/metadata/mysql"
1418
)
1519

20+
type metaReader struct {
21+
metadata.LoggingReader
22+
}
23+
24+
var (
25+
_ metadata.CatalogReader = &metaReader{}
26+
_ metadata.ColumnStatReader = &metaReader{}
27+
)
28+
29+
func (r metaReader) Catalogs(metadata.Filter) (*metadata.CatalogSet, error) {
30+
qstr := `SHOW catalogs`
31+
rows, closeRows, err := r.Query(qstr)
32+
if err != nil {
33+
return nil, err
34+
}
35+
defer closeRows()
36+
37+
results := []metadata.Catalog{}
38+
for rows.Next() {
39+
rec := metadata.Catalog{}
40+
err = rows.Scan(&rec.Catalog)
41+
if err != nil {
42+
return nil, err
43+
}
44+
results = append(results, rec)
45+
}
46+
if rows.Err() != nil {
47+
return nil, rows.Err()
48+
}
49+
return metadata.NewCatalogSet(results), nil
50+
}
51+
52+
func (r metaReader) ColumnStats(f metadata.Filter) (*metadata.ColumnStatSet, error) {
53+
names := []string{}
54+
if f.Catalog != "" {
55+
names = append(names, f.Catalog+".")
56+
}
57+
if f.Schema != "" {
58+
names = append(names, f.Schema+".")
59+
}
60+
names = append(names, f.Parent)
61+
rows, closeRows, err := r.Query(fmt.Sprintf("SHOW STATS FOR %s", strings.Join(names, "")))
62+
if err != nil {
63+
return nil, err
64+
}
65+
defer closeRows()
66+
67+
results := []metadata.ColumnStat{}
68+
for rows.Next() {
69+
rec := metadata.ColumnStat{Catalog: f.Catalog, Schema: f.Schema, Table: f.Parent}
70+
name := sql.NullString{}
71+
avgWidth := sql.NullInt32{}
72+
numDistinct := sql.NullInt64{}
73+
nullFrac := sql.NullFloat64{}
74+
numRows := sql.NullInt64{}
75+
min := sql.NullString{}
76+
max := sql.NullString{}
77+
err = rows.Scan(
78+
&name,
79+
&avgWidth,
80+
&numDistinct,
81+
&nullFrac,
82+
&numRows,
83+
&min,
84+
&max,
85+
)
86+
if err != nil {
87+
return nil, err
88+
}
89+
if !name.Valid {
90+
continue
91+
}
92+
rec.Name = name.String
93+
if avgWidth.Valid {
94+
rec.AvgWidth = int(avgWidth.Int32)
95+
}
96+
if numDistinct.Valid {
97+
rec.NumDistinct = numDistinct.Int64
98+
}
99+
if nullFrac.Valid {
100+
rec.NullFrac = nullFrac.Float64
101+
}
102+
if min.Valid {
103+
rec.Min = min.String
104+
}
105+
if max.Valid {
106+
rec.Max = max.String
107+
}
108+
results = append(results, rec)
109+
}
110+
if rows.Err() != nil {
111+
return nil, rows.Err()
112+
}
113+
114+
return metadata.NewColumnStatSet(results), nil
115+
}
116+
16117
func init() {
118+
newReader := func(db drivers.DB, opts ...metadata.ReaderOption) metadata.Reader {
119+
ir := infos.New(
120+
infos.WithPlaceholder(func(int) string { return "?" }),
121+
infos.WithCustomClauses(map[infos.ClauseName]string{
122+
infos.ColumnsColumnSize: "0",
123+
infos.ColumnsNumericScale: "0",
124+
infos.ColumnsNumericPrecRadix: "0",
125+
infos.ColumnsCharOctetLength: "0",
126+
}),
127+
infos.WithFunctions(false),
128+
infos.WithSequences(false),
129+
infos.WithIndexes(false),
130+
infos.WithConstraints(false),
131+
infos.WithColumnPrivileges(false),
132+
infos.WithUsagePrivileges(false),
133+
)(db, opts...)
134+
mr := &metaReader{
135+
LoggingReader: metadata.NewLoggingReader(db, opts...),
136+
}
137+
return metadata.NewPluginReader(ir, mr)
138+
}
17139
drivers.Register("duckdb", drivers.Driver{
18140
AllowMultilineComments: true,
19141
Version: func(ctx context.Context, db drivers.DB) (string, error) {
@@ -24,9 +146,9 @@ func init() {
24146
}
25147
return "DuckDB " + ver, nil
26148
},
27-
NewMetadataReader: mymeta.NewReader,
149+
NewMetadataReader: newReader,
28150
NewMetadataWriter: func(db drivers.DB, w io.Writer, opts ...metadata.ReaderOption) metadata.Writer {
29-
return metadata.NewDefaultWriter(mymeta.NewReader(db, opts...))(db, w)
151+
return metadata.NewDefaultWriter(newReader(db, opts...))(db, w)
30152
},
31153
Copy: drivers.CopyWithInsert(func(int) string { return "?" }),
32154
NewCompleter: mymeta.NewCompleter,

0 commit comments

Comments
 (0)