Skip to content

Commit e07058e

Browse files
authored
Handle 0 rows (#57)
* Handle 0 rows * Fix for tests * Update readme
1 parent 8f88b40 commit e07058e

File tree

3 files changed

+75
-45
lines changed

3 files changed

+75
-45
lines changed

README.md

+18
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,24 @@ file into SQLite.
454454
So even if you change the query, as long as the file doesn't change,
455455
the cache is effective.
456456
457+
### Interactive REPL
458+
459+
Use the `-i` or `--interactive` flag to enter an interactive REPL
460+
where you can run multiple SQL queries.
461+
462+
```
463+
$ dsq some-large-file.json -i
464+
dsq> SELECT COUNT(1) FROM {};
465+
+----------+
466+
| COUNT(1) |
467+
+----------+
468+
| 1000 |
469+
+----------+
470+
(1 row)
471+
dsq> SELECT * FROM {} WHERE NAME = 'Kevin';
472+
(0 rows)
473+
```
474+
457475
## Supported Data Types
458476
459477
| Name | File Extension(s) | Mime Type | Notes |

main.go

+53-43
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"io/ioutil"
1212
"log"
1313
"os"
14+
"path"
1415
"path/filepath"
1516
"regexp"
1617
"sort"
@@ -97,6 +98,12 @@ func dumpJSONFile(file string, pretty bool, schema bool) error {
9798
}
9899
defer fd.Close()
99100

101+
size := int64(-1)
102+
fi, err := fd.Stat()
103+
if err == nil {
104+
size = fi.Size()
105+
}
106+
100107
if schema {
101108
s, err := runner.ShapeFromFile(file, "doesn't-matter", runner.DefaultShapeMaxBytesToRead, 100)
102109
if err != nil {
@@ -124,48 +131,57 @@ func dumpJSONFile(file string, pretty bool, schema bool) error {
124131
return nil
125132
}
126133

127-
s, err := runner.ShapeFromFile(file, "doesn't-matter", runner.DefaultShapeMaxBytesToRead, 100)
128-
if err != nil {
129-
return err
130-
}
131-
var columns []string
132-
for name := range s.ArrayShape.Children.ObjectShape.Children {
133-
columns = append(columns, name)
134-
}
135-
sort.Strings(columns)
134+
var rows []map[string]interface{}
135+
if size != 0 {
136+
s, err := runner.ShapeFromFile(file, "doesn't-matter", runner.DefaultShapeMaxBytesToRead, 100)
137+
if err != nil {
138+
return err
139+
}
140+
var columns []string
141+
for name := range s.ArrayShape.Children.ObjectShape.Children {
142+
columns = append(columns, name)
143+
}
144+
sort.Strings(columns)
136145

137-
table := tablewriter.NewWriter(os.Stdout)
138-
table.SetHeader(columns)
139-
table.SetAutoFormatHeaders(false)
146+
table := tablewriter.NewWriter(os.Stdout)
147+
table.SetHeader(columns)
148+
table.SetAutoFormatHeaders(false)
140149

141-
dec := json.NewDecoder(fd)
142-
var rows []map[string]interface{}
143-
err = dec.Decode(&rows)
144-
if err != nil {
145-
return err
146-
}
150+
dec := json.NewDecoder(fd)
151+
err = dec.Decode(&rows)
152+
if err != nil {
153+
return err
154+
}
147155

148-
for _, objRow := range rows {
149-
var row []string
150-
for _, column := range columns {
151-
var cell string
152-
switch t := objRow[column].(type) {
153-
case bool, byte, complex64, complex128, error, float32, float64,
154-
int, int8, int16, int32, int64,
155-
uint, uint16, uint32, uint64, uintptr:
156-
cell = fmt.Sprintf("%#v", t)
157-
case string:
158-
cell = t
159-
default:
160-
cellBytes, _ := json.Marshal(t)
161-
cell = string(cellBytes)
156+
for _, objRow := range rows {
157+
var row []string
158+
for _, column := range columns {
159+
var cell string
160+
switch t := objRow[column].(type) {
161+
case bool, byte, complex64, complex128, error, float32, float64,
162+
int, int8, int16, int32, int64,
163+
uint, uint16, uint32, uint64, uintptr:
164+
cell = fmt.Sprintf("%#v", t)
165+
case string:
166+
cell = t
167+
default:
168+
cellBytes, _ := json.Marshal(t)
169+
cell = string(cellBytes)
170+
}
171+
row = append(row, cell)
162172
}
163-
row = append(row, cell)
173+
table.Append(row)
164174
}
165-
table.Append(row)
175+
176+
table.Render()
177+
}
178+
179+
if len(rows) == 1 {
180+
fmt.Println("(1 row)")
181+
} else {
182+
fmt.Printf("(%d rows)\n", len(rows))
166183
}
167184

168-
table.Render()
169185
return nil
170186
}
171187

@@ -251,13 +267,6 @@ func runQuery(queryRaw string, project *runner.ProjectState, ec *runner.EvalCont
251267
}
252268

253269
func repl(project *runner.ProjectState, ec *runner.EvalContext, args *args, files []string) error {
254-
tempfile, err := ioutil.TempFile("", "dsq-hist")
255-
if err != nil {
256-
return err
257-
}
258-
259-
defer os.Remove(tempfile.Name())
260-
261270
completer := readline.NewPrefixCompleter(
262271
readline.PcItem("SELECT"),
263272
readline.PcItem("FROM"),
@@ -277,9 +286,10 @@ func repl(project *runner.ProjectState, ec *runner.EvalContext, args *args, file
277286
return r, true
278287
}
279288

289+
historyFile := path.Join(runner.HOME, "dsq_history")
280290
l, err := readline.NewEx(&readline.Config{
281291
Prompt: "dsq> ",
282-
HistoryFile: tempfile.Name(),
292+
HistoryFile: historyFile,
283293
InterruptPrompt: "^D",
284294
EOFPrompt: "exit",
285295
HistorySearchFold: true,

scripts/test.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ def test(name, to_run, want, fail=False, sort=False, winSkip=False, within_secon
183183
+----+-------+
184184
| 1 | Corah |
185185
| 3 | Minh |
186-
+----+-------+"""
186+
+----+-------+
187+
(2 rows)"""
187188
test("Pretty column order alphabetical", to_run, want)
188189

189190
# Pretty without query
@@ -192,7 +193,8 @@ def test(name, to_run, want, fail=False, sort=False, winSkip=False, within_secon
192193
| a | b | c |
193194
+---+---+-------+
194195
| 1 | 2 | [1,2] |
195-
+---+---+-------+"""
196+
+---+---+-------+
197+
(1 row)"""
196198
test("Pretty works even without query", to_run, want)
197199

198200
# Prints schema pretty

0 commit comments

Comments
 (0)