Code Monkey home page Code Monkey logo

trdsql's Introduction

trdsql

PkgGoDev Go Report Card Go Coverage GitHub Actions

trdsql is a CLI tool that can execute SQL queries on CSV, LTSV, JSON, YAML and TBLN files.

This tool is similar to others such as q and textql, with a key distinction: it allows the use of PostgreSQL or MySQL syntax.

For usage as a library, please refer to the godoc and the provided examples.

trdsql.gif

1. INSTALL

1.1. go get

go get -d github.com/noborus/trdsql
cd $GOPATH/src/github.com/noborus/trdsql
make
make install

1.1.1. Requirements

go 1.19 or higher.

1.2. Download binary

Download binary from the releases page(Linux/Windows/macOS).

1.3. Homebrew

brew install noborus/tap/trdsql

1.4. MacPorts

sudo port selfupdate
sudo port install trdsql

1.5. FreeBSD

freshports

pkg install trdsql

1.6. Cgo free

Typically, go-sqlite3 is used for building. However, if you're building with CGO_ENABLED=0, consider using sqlite instead.

Building without CGO (CGO Free) can reduce issues related to cross-compiling, but it may result in slower execution times.

2. Docker

2.1. Docker pull

Pull the latest image from the Docker hub.

docker pull noborus/trdsql

2.2. image build

Or build it yourself.

docker build -t trdsql .

2.3. Docker Run

Docker run.

docker run --rm -it -v $(pwd):/tmp trdsql [options and commands]

3. Usage

To use trdsql, you can either specify an SQL query or simply provide a file for conversion.

trdsql [options] SQL

For file conversion, this is equivalent to executing 'trdsql -o[output format] "SELECT * FROM filename"'.

trdsql -o[output format] -t [input filename]

3.1. Global options

  • -a filename analyze the file and suggest SQL.
  • -A filename analyze the file but only suggest SQL.
  • -config filename configuration file location.
  • -db db name specify db name of the setting.
  • -dblist display db list of configure.
  • -driver string database driver. [ mysql | postgres | sqlite3 | sqlite(CGO Free) ] (default "sqlite3")
  • -dsn string database driver specific data source name.
  • -debug debug print.
  • -help display usage information.
  • -q filename read query from the specified file.
  • -t filename read table name from the specified file.
  • -version display version information.

3.2. Input formats

  • -ig guess format from extension. (default)
  • -icsv CSV format for input.
  • -ijson JSON format for input.
  • -iltsv LTSV format for input.
  • -iyaml YAML format for input.
  • -itbln TBLN format for input.
  • -iwidth width specification format for input.

3.2.1. Input options

  • -ih the first line is interpreted as column names(CSV only).
  • -id character field delimiter for input(default ",")(CSV only).
  • -ijq string jq expression string for input(JSON/JSONL only).
  • -ilr int limited number of rows to read.
  • -inull string value(string) to convert to null on input.
  • -ir int number of rows to preread. (default 1)
  • -is int skip header row.

3.3. Output formats

  • -ocsv CSV format for output. (default)
  • -ojson JSON format for output.
  • -ojsonl JSONL(JSON Lines) format for output.
  • -oltsv LTSV format for output.
  • -oat ASCII Table format for output.
  • -omd Markdown format for output.
  • -oraw Raw format for output.
  • -ovf Vertical format for output.
  • -oyaml YAML format for output.
  • -otbln TBLN format for output.

Or, guess the output format by file name.

3.3.1. Output options

  • -out filename output file name.
  • -out-without-guess output without guessing (when using -out).
  • -oh output column name as header.
  • -od character field delimiter for output. (default ",")(CSV and RAW only).
  • -oq character quote character for output. (default """)(CSV only).
  • -oaq enclose all fields in quotes for output(CSV only).
  • -ocrlf use CRLF for output. End each output line with '\r\n' instead of '\n'."(CSV only).
  • -onowrap do not wrap long columns(AT and MD only).
  • -onull value(string) to convert from null on output.
  • -oz string compression format for output. [ gzip | bz2 | zstd | lz4 | xz ]

3.4. Handling of NULL

NULL is undecided in many text formats. JSON null is considered the same as SQL NULL. For formats other than JSON, you must specify a string that is considered NULL. In most cases you will need to specify an empty string ("").

If -inull "" is specified, an empty string will be treated as SQL NULL.

SQL NULL is an empty string by default. Specify the -onull "(NULL)" option if you want a different string.

$ echo "1,,v" | trdsql -inull "" -onull "(NULL)" "SELECT * FROM -"
1,(NULL),v

In the case of JSON, null is NULL as it is, and the specified string is converted to NULL.

$ echo '[1,null,""]' | trdsql -inull "" -ojson -ijson "SELECT * FROM -"
[
  {
    "c1": "1"
  },
  {
    "c1": null
  },
  {
    "c1": null
  }
]

3.5. Multiple queries

Multiple queries can be executed by separating them with a semicolon. Update queries must be followed by a SELECT statement.

$ trdsql "UPDATE SET c2='banana' WHERE c3='1';SELECT * FROM test.csv"
1,Orange
2,Melon
3,banana

You can perform multiple SELECTs, but the output will be in one format.

$ trdsql -oh "SELECT c1,c2 FROM test.csv;SELECT c2,c1 FROM test.csv"
c1,c2
1,Orange
2,Melon
3,Apple
c2,c1
Orange,1
Melon,2
Apple,3

4. Example

test.csv file.

1,Orange
2,Melon
3,Apple

Please write a file name like a table name.

trdsql "SELECT * FROM test.csv"

-q filename can execute SQL from file

trdsql -q test.sql

4.1. STDIN input

"-" or "stdin" is received from standard input instead of file name.

cat test.csv | trdsql "SELECT * FROM -"

or

cat test.csv | trdsql "SELECT * FROM stdin"

4.2. Multiple files

Multiple matched files can be executed as one table.

$ trdsql -ih "SELECT * FROM tt*.csv"
1,test1
2,test2
3,test3

Note

It is not possible to mix different formats (ex: CSV and LTSV).

4.3. Compressed files

If the file is compressed with gzip, bz2, zstd, lz4, xz, it will be automatically uncompressed.

trdsql "SELECT * FROM testdata/test.csv.gz"
trdsql "SELECT * FROM testdata/test.csv.zst"

It is possible to mix uncompressed and compressed files using wildcards.

trdsql "SELECT * FROM testdata/test.csv*"

4.4. Output file

-out filename option to output the file to a file.

trdsql -out result.csv "SELECT * FROM testdata/test.csv ORDER BY c1"

4.5. Output compression

-oz compression type to compress and output.

trdsql -oz gz "SELECT * FROM testdata/test.csv ORDER BY c1" > result.csv.gz

4.6. Guess by output file name

The filename of -out filename option determines the output format(csv, ltsv, json, tbln, raw, md, at, vf, jsonl) and compression format(gzip, bz2, zstd,lz4, xz) by guess.

Guess by extension output format + output compression (eg .csv.gz, .ltsv.lz4, .md.zst ...).

The following is an LTSV file compressed in zstd.

trdsql -out result.ltsv.zst "SELECT * FROM testdata/test.csv"

4.7. Columns is not constant

If the number of columns is not a constant, read and decide multiple rows.

$ trdsql -ir 3 -iltsv "SELECT * FROM test_indefinite.ltsv"
1,Orange,50,,
2,Melon,500,ibaraki,
3,Apple,100,aomori,red

4.8. TSV (Tab Separated Value)

-id "\\t" is input from TSV (Tab Separated Value)

1	Orange
2	Melon
3	Apple
trdsql -id "\t" "SELECT * FROM test-tab.csv"

-od "\\t" is TSV (Tab Separated Value) output.

$ trdsql -od "\t" "SELECT * FROM test.csv"
1	Orange
2	Melon
3	Apple

4.9. LTSV (Labeled Tab-separated Values)

-iltsv is input from LTSV(Labeled Tab-separated Values).

sample.ltsv

id:1	name:Orange	price:50
id:2	name:Melon	price:500
id:3	name:Apple	price:100
trdsql -iltsv "SELECT * FROM sample.ltsv"
1,Orange,50
2,Melon,500
3,Apple,100

Note

Only the columns in the first row are targeted.

-oltsv is LTSV(Labeled Tab-separated Values) output.

$ trdsql -iltsv -oltsv "SELECT * FROM sample.ltsv"
id:1	name:Orange	price:50
id:2	name:Melon	price:500
id:3	name:Apple	price:100

4.10. JSON

-ijson is input from JSON.

sample.json

[
  {
    "id": "1",
    "name": "Orange",
    "price": "50"
  },
  {
    "id": "2",
    "name": "Melon",
    "price": "500"
  },
  {
    "id": "3",
    "name": "Apple",
    "price": "100"
  }
]
$ trdsql -ijson "SELECT * FROM sample.json"
1,Orange,50
2,Melon,500
3,Apple,100

JSON can contain structured types, but trdsql is stored as it is as JSON string.

sample2.json

[
    {
      "id": 1,
      "name": "Drolet",
      "attribute": { "country": "Maldives", "color": "burlywood" }
    },
    {
      "id": 2,
      "name": "Shelly",
      "attribute": { "country": "Yemen", "color": "plum" }
    },
    {
      "id": 3,
      "name": "Tuck",
      "attribute": { "country": "Mayotte", "color": "antiquewhite" }
    }
]
$ trdsql -ijson "SELECT * FROM sample2.json"
1,Drolet,"{""color"":""burlywood"",""country"":""Maldives""}"
2,Shelly,"{""color"":""plum"",""country"":""Yemen""}"
3,Tuck,"{""color"":""antiquewhite"",""country"":""Mayotte""}"

Please use SQL function.

$ trdsql -ijson "SELECT id, name, JSON_EXTRACT(attribute,'$.country'), JSON_EXTRACT(attribute,'$.color') FROM sample2.json"
1,Drolet,Maldives,burlywood
2,Shelly,Yemen,plum
3,Tuck,Mayotte,antiquewhite

4.10.1. jq expression

If json has a hierarchy, you can filter by jq expression.

The jq expression is implemented using gojq.

menu.json

{
	"menu": {
		"id": "file",
		"value": "File",
		"popup": {
			"menuitem": [
				{
					"value": "New",
					"onclick": "CreateDoc()"
				},
				{
					"value": "Open",
					"onclick": "OpenDoc()"
				},
				{
					"value": "Save",
					"onclick": "SaveDoc()"
				}
			]
		}
	}
}

You can write a jq expression by connecting :: after the json file name. Enclose the jq expression in double quotes if needed.

trdsql -oat 'SELECT value, onclick FROM menu.json::".menu.popup.menuitem"'

Or specify with the -ijq option.

$ trdsql -oat -ijq ".menu.popup.menuitem" "SELECT * FROM menu.json"
+-------+-------------+
| value |   onclick   |
+-------+-------------+
| New   | CreateDoc() |
| Open  | OpenDoc()   |
| Save  | SaveDoc()   |
+-------+-------------+

Example to use instead of gojq.

$ echo '{"foo": 128}' | trdsql -ijson "SELECT * FROM -::'.foo'"
128
$ echo '{"a": {"b": 42}}' | trdsql -ijson "SELECT * FROM -::'.a.b'"
42
$ echo '{"id": "sample", "10": {"b": 42}}' | trdsql -ijson "SELECT * FROM -::'{(.id): .[\"10\"].b}'"
42
$ echo '[{"id":1},{"id":2},{"id":3}]' | trdsql -ijson "SELECT * FROM -::'.[] | .id'"
1
2
3
$ echo '{"a":1,"b":2}' | trdsql -ijson "SELECT * FROM -::'.a += 1 | .b *= 2'"
4,2
$ echo '{"a":1} [2] 3' | trdsql -ijson "SELECT * FROM -::'. as {\$a} ?// [\$a] ?// \$a | \$a'"
1
2
3

4.11. JSONL(NDJSON)

Another json format. JSONL(JSON Lines). It is also called ndjson.

sample2.json

{"id": "1","name": "Orange","price": "50"}
{"id": "2","name": "Melon","price": "500"}
{"id": "3","name": "Apple","price": "100"}

-ojson is JSON Output.

$ trdsql -ojson "SELECT * FROM test.csv"
[
  {
    "c1": "1",
    "c2": "Orange"
  },
  {
    "c1": "2",
    "c2": "Melon"
  },
  {
    "c1": "3",
    "c2": "Apple"
  }
]

To output in JSONL, specify -ojsonl.

$ trdsql -ojsonl "SELECT * FROM test.csv"
{"c1":"1","c2":"Orange"}
{"c1":"2","c2":"Melon"}
{"c1":"3","c2":"Apple"}

4.12. YAML

-iyaml is input from YAML (Or if the extension is yaml or yml, it is considered a YAML file).

sample.yaml

- id: 1
  name: Orange
  price: 50
- id: 2
  name: Melon
  price: 500
- id: 3
  name: Apple
  price: 100
$ trdsql -iyaml -ocsv "SELECT * FROM sample.yaml"
1,Orange,50
2,Melon,500
3,Apple,100

Since yaml is internally converted to JSON, it can be converted to json and output.

sample2.yaml

a: true
b:
  c: 2
  d: [3, 4, 5]
  e:
    - name: fred
      value: 3
    - name: sam
      value: 4%
$ trdsql -ojson "SELECT * FROM sample2.yaml"
[
  {
    "a": "true",
    "b": {
      "c": 2,
      "d": [
        3,
        4,
        5
      ],
      "e": [
        {
          "name": "fred",
          "value": 3
        },
        {
          "name": "sam",
          "value": "4%"
        }
      ]
    }
  }
]

So in addition you can also use jq syntax.

$ trdsql  -ojson "SELECT * FROM sample2.yaml::.b.e"
[
  {
    "name": "fred",
    "value": "3"
  },
  {
    "name": "sam",
    "value": "4%"
  }
]

json can be converted to yaml.

$ trdsql  -ojson "SELECT * FROM sample2.yaml::.b.e"
- name: fred
  value: 3
- name: sam
  value: 4%

4.13. TBLN

-itbln is input from TBLN.

sample.tbln

; name: | id | name |
; type: | int | text |
| 1 | Bob |
| 2 | Alice |
$ trdsql -itbln "SELECT * FROM sample.tbln"
1,Bob
2,Alice

TBLN file reflects extras name and type.

-otbln is TBLN Output.

$ trdsql -otbln "SELECT c1::int as id, c2::text as name FROM test.csv"
; created_at: 2019-03-22T13:20:31+09:00
; name: | id | name |
; type: | int | text |
| 1 | Orange |
| 2 | Melon |
| 3 | Apple |

TBLN can contain column names and type definitions. Please refer to https://tbln.dev/ for details of TBLN.

4.14. WIDTH

-iwidth inputs the format specifying the width. This is used when the header column width represents the body column width.

$ ps | trdsql -oh -iwidth "SELECT * FROM -"
PID,TTY,TIME,CMD
302965,pts/3,00:00:12,zsh
733211,pts/3,00:00:00,ps
733212,pts/3,00:00:00,tee
733213,pts/3,00:00:00,guesswidth

-id " " for CSV also works in many cases. But -id " " does not recognize spaces in columns very well.

-iwidth recognizes column widths and space separators.

4.15. Raw output

-oraw is Raw Output. It is used when "escape processing is unnecessary" in CSV output. (For example, when outputting JSON in the database).

$ trdsql -oraw "SELECT row_to_json(t,TRUE) FROM test.csv AS t"
{"c1":"1",
 "c2":"Orange"}
{"c1":"2",
 "c2":"Melon"}
{"c1":"3",
 "c2":"Apple"}

Multiple delimiter characters can be used for raw.

$ trdsql -oraw -od "\t|\t" -db pdb "SELECT * FROM test.csv"
1	|	Orange
2	|	Melon
3	|	Apple

4.16. ASCII Table & MarkDown output

-oat is ASCII table output.

$ trdsql -oat "SELECT * FROM test.csv"
+----+--------+
| C1 |   C2   |
+----+--------+
|  1 | Orange |
|  2 | Melon  |
|  3 | Apple  |
+----+--------+

-omd is Markdown output.

$ trdsql -omd "SELECT * FROM test.csv"
| C1 |   C2   |
|----|--------|
|  1 | Orange |
|  2 | Melon  |
|  3 | Apple  |

The -onowrap option does not wrap long columns in at or md output.

4.17. Vertical format output

-ovf is Vertical format output("column name | value" vertically).

$ trdsql -ovf "SELECT * FROM test.csv"
---[ 1]--------------------------------------------------------
  c1 | 1
  c2 | Orange
---[ 2]--------------------------------------------------------
  c1 | 2
  c2 | Melon
---[ 3]--------------------------------------------------------
  c1 | 3
  c2 | Apple

5. SQL

5.1. SQL function

$ trdsql "SELECT count(*) FROM test.csv"
3

The default column names are c1, c2,...

$ trdsql "SELECT c2,c1 FROM test.csv"
Orange,1
Melon,2
Apple,3

Note

the available functions and their syntax depend on the driver you have chosen (mysql or postgres or sqlite). The default one is sqlite.

5.2. JOIN

The SQL JOIN can be used.

user.csv

1,userA
2,userB

hist.csv

1,2017-7-10
2,2017-7-10
2,2017-7-11
$ trdsql "SELECT u.c1,u.c2,h.c2 FROM user.csv as u LEFT JOIN hist.csv as h ON(u.c1=h.c1)"
1,userA,2017-7-10
2,userB,2017-7-10
2,userB,2017-7-11

5.3. PostgreSQL

When using PostgreSQL, specify postgres for driver and driver-specific data source name for dsn.

trdsql -driver postgres -dsn "dbname=test" "SELECT count(*) FROM test.csv "

5.3.1. Function

The PostgreSQL driver can use the window function.

$ trdsql -driver postgres -dsn "dbname=test" "SELECT row_number() OVER (ORDER BY c2),c1,c2 FROM test.csv"
1,3,Apple
2,2,Melon
3,1,Orange

For example, the generate_series function can be used.

$ trdsql -driver postgres -dsn "dbname=test" "SELECT generate_series(1,3);"
1
2
3

5.3.2. Join table and CSV file is possible

Test database has a colors table.

$ psql test -c "SELECT * FROM colors"
 id |  name  
----+--------
  1 | orange
  2 | green
  3 | red
(3 rows)

Join table and CSV file.

$ trdsql -driver postgres -dsn "dbname=test" "SELECT t.c1,t.c2,c.name FROM test.csv AS t LEFT JOIN colors AS c ON (t.c1::int = c.id)"
1,Orange,orange
2,Melon,green
3,Apple,red

To create a table from a file, use "CREATE TABLE ... AS SELECT...".

trdsql -driver postgres -dns "dbname=test" "CREATE TABLE fruits (id, name) AS SELECT c1::int, c2 FROM fruits.csv "
$ psql -c "SELECT * FROM fruits;"
 id |  name  
----+--------
  1 | Orange
  2 | Melon
  3 | Apple
(3 rows)

5.4. MySQL

When using MySQL, specify mysql for driver and connection information for dsn.

$ trdsql -driver mysql -dsn "user:password@/test" "SELECT GROUP_CONCAT(c2 ORDER BY c2 DESC) FROM testdata/test.csv"
"g,d,a"
$ trdsql -driver mysql -dsn "user:password@/test" "SELECT c1, SHA2(c2,224) FROM test.csv"
1,a063876767f00792bac16d0dac57457fc88863709361a1bb33f13dfb
2,2e7906d37e9523efeefb6fd2bc3be6b3f2991678427bedc296f9ddb6
3,d0b8d1d417a45c7c58202f55cbb617865f1ef72c606f9bce54322802

MySQL can join tables and CSV files as well as PostgreSQL.

5.5. Analyze

The -a filename option parses the file and outputs table information and SQL examples.

$ trdsql -a testdata/test.ltsv
The table name is testdata/header.csv.
The file type is CSV.

Data types:
+-------------+------+
| column name | type |
+-------------+------+
| id          | text |
| \`name\`    | text |
+-------------+------+

Data samples:
+----+----------+
| id | \`name\` |
+----+----------+
|  1 | Orange   |
+----+----------+

Examples:
trdsql -db sdb -ih "SELECT id, \`name\` FROM testdata/header.csv"
trdsql -db sdb -ih "SELECT id, \`name\` FROM testdata/header.csv WHERE id = '1'"
trdsql -db sdb -ih "SELECT id, count(id) FROM testdata/header.csv GROUP BY id"
trdsql -db sdb -ih "SELECT id, \`name\` FROM testdata/header.csv ORDER BY id LIMIT 10"

Other options(-id,-ih,-ir,-is,icsv,iltsv,-ijson,-itbln...) are available.

trdsql -ih -a testdata/header.csv

Similarly, with -A filename option, only Examples (SQL) is output.

$ trdsql -ih -A testdata/header.csv
trdsql -ih "SELECT id, \`name\` FROM testdata/header.csv"
trdsql -ih "SELECT id, \`name\` FROM testdata/header.csv WHERE id = '1'"
trdsql -ih "SELECT id, count(id) FROM testdata/header.csv GROUP BY id"
trdsql -ih "SELECT id, \`name\` FROM testdata/header.csv ORDER BY id LIMIT 10"

5.6. Configuration

You can specify driver and dsn in the configuration file.

Unix like.

${HOME}/.config/trdsql/config.json

Windows (ex).

C:\Users\{"User"}\AppData\Roaming\trdsql\config.json

Or use the -config file option.

trdsql -config config.json "SELECT * FROM test.csv"

sample: config.json

{
  "db": "pdb",
  "database": {
    "sdb": {
      "driver": "sqlite3",
      "dsn": ""
    },
    "pdb": {
      "driver": "postgres",
      "dsn": "user=test dbname=test"
    },
    "mdb": {
      "driver": "mysql",
      "dsn": "user:password@/dbname"
    }
  }
}

The default database is an entry of "db".

If you put the setting in you can specify the name with -db.

$ trdsql -debug -db pdb "SELECT * FROM test.csv"
2017/07/18 02:27:47 driver: postgres, dsn: user=test dbname=test
2017/07/18 02:27:47 CREATE TEMPORARY TABLE "test.csv" ( c1 text,c2 text );
2017/07/18 02:27:47 INSERT INTO "test.csv" (c1,c2) VALUES ($1,$2);
2017/07/18 02:27:47 SELECT * FROM "test.csv"
1,Orange
2,Melon
3,Apple

6. Library

Example of use as a library.

package main

import (
        "log"

        "github.com/noborus/trdsql"
)

func main() {
        trd := trdsql.NewTRDSQL(
                trdsql.NewImporter(trdsql.InDelimiter(":")),
                trdsql.NewExporter(trdsql.NewWriter()),
        )
        if err := trd.Exec("SELECT c1 FROM /etc/passwd"); err != nil {
                log.Fatal(err)
        }
}

Please refer to godoc and _example for usage as a library.

7. See also

  • psutilsql - A tool for querying system status in SQL.
  • mdtsql - A tool for querying markdown tables in SQL.
  • xlsxsql - A tool for querying Excel files in SQL.

8. Learn More

9. License

MIT

Please check each license of SQL driver.

trdsql's People

Contributors

aborruso avatar dependabot[bot] avatar herbygillot avatar jetzerb avatar masavini avatar noborus avatar ser1zw avatar suzuki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

trdsql's Issues

-driver postgres returns SSL error

trdsql -driver postgres -ih -ocsv "SELECT * FROM file.csv WHERE lpad(a, 9, '0') != replace(b, '-', '') LIMIT 10"
2021/06/02 13:03:49 begin: pq: SSL is not enabled on the server

I'm not sure what I'm supposed to do here. I just wanted to use the lpad function thus I added the -driver option. Setting up SSL on a localhost instance seems overkill.

Make this project dependency ready

I would like to use this as a dependency of my own application, however I cannot use it as such because all the code is in the main package.

Please move supporting code to it's own package and reference from your main.go so this can be used from other go programs.

Moreover, structs appear to use all private fields, so those would need to be updated as well.

Please also provide an option to supply an input stream to the TRDSQL struct, instead of assuming a file.

CSV Column Name not recognized

I'm not sure what I'm doing wrong.

I'm trying to read from a csv with the columns Engine_name, Variable_name and Value.
However, for some reason the Engine_name column is not recognized as a header column.
Here are the queries I tried:
Get some of in on the data to confirm the data is there: trdsql -ih -a mysql_5.7.x_settings.csv
Output:
The table name is mysql_5.7.x_settings.csv.
The file type is CSV.

Data types:
+-------------------+------+
| column name | type |
+-------------------+------+
| `Engine_name` | text |
| `Variable_name` | text |
| `Value` | text |
+-------------------+------+

Data samples:
+-----------------+---------------------------------------+-------------------------------+
| `Engine_name` | `Variable_name` | `Value` |
+-----------------+---------------------------------------+-------------------------------+
| MySQL 5.7.X | aurora_backtrace_compare_metrics_file | backtrace_compare_metrics.txt |
+-----------------+---------------------------------------+-------------------------------+

Examples:
trdsql -ih "SELECT `Engine_name`, `Variable_name`, `Value` FROM mysql_5.7.x_settings.csv"
trdsql -ih "SELECT `Engine_name`, `Variable_name`, `Value` FROM mysql_5.7.x_settings.csv WHERE `Engine_name` = 'MySQL 5.7.X'"
trdsql -ih "SELECT `Engine_name`, count(`Engine_name`) FROM mysql_5.7.x_settings.csv GROUP BY `Engine_name`"
trdsql -ih "SELECT `Engine_name`, `Variable_name`, `Value` FROM mysql_5.7.x_settings.csv ORDER BY `Engine_name` LIMIT 10"

I tried:
trdsql -ih "SELECT `Engine_name`, `Variable_name`, `Value` FROM mysql_5.7.x_settings.csv ORDER BY `Engine_name` LIMIT 10"
2024/04/17 09:29:08 export: no such column: Engine_name [SELECT Engine_name, Variable_name, Value FROM mysql_5.7.x_settings.csv ORDER BY Engine_name LIMIT 10]

I tried:
trdsql -ih "SELECT Engine_name, Variable_name, Value FROM mysql_5.7.x_settings.csv"
2024/04/17 09:29:27 export: no such column: Engine_name [SELECT Engine_name, Variable_name, Value FROM mysql_5.7.x_settings.csv]

Btw, great job on this tool. I just started using and sharing it internally.

feature request: automatically quote columns

Hello,

I've jsut discovered this great tool, which is incredible, except for this ugly ` quote character required when column names are not fully lowercased, which is really awful in our bash scripts...

I wonder if it was possible to have some sort of generic way of quoting columns, that can be automatically converted to the good column quote depending on the DB driver.

The idea is to allow something like SELECT [Id], [Name] FROM something and have it converted automatically to " or `.

Maybe the [...] is not the good solution, if some drivers support it, so we may want to switch to something else like {...} or |...|.
It should be something that can be used for all known DB drivers.

The complex thing is to parse the SQL string to detect what is inside strings and what is not, to perform the replacement only on the SQL part of the query.

What do you think?

Hi is there any versions of trdsql that work with "GLIBC_2.28"?

Hi,

Thank you so much for this product. The team I work on has used this quite a bit. I have had to upgrade to Oracle Linux 8.8 and I am trying to get trdsql installed on this box.

I have downloaded the latest version and I am running into the error
/lib64/libm.so.6: version `GLIBC_2.29' not found (required by ./trdsql)

I have subsequently downloaded earlier versions of the *_linux_amd64.zip and run into the same problem each time. Are you aware of a version or something I can do to get this to run with glibc_2.28?

Thank you so much for your time and effort,
Joe

binary is not completely statically compiled

$ trdsql -ijson "select verbose_name from fudaneducn.json group by verbose_name"
trdsql: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by trdsql)
trdsql: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by trdsql)
trdsql: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by trdsql)

It depends on a particular version of glibc

my glibc info

strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_2.27
GLIBC_PRIVATE
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27.

`-ijq` does not work correctly from stdin

Hi! Thanks for creating trdsql - it's awesome!

I just discovered this tool and I think it will on many occasions replace jq for me. But I think I've found a minor bug in the current version 0.9.1.

It's best shown using an example.

This works:

$ cat customer_basedata.json | trdsql -ijson 'SELECT id, name FROM -::.entities'

Also works:

$ trdsql -ijq '.entities' 'SELECT id, name FROM customer_basedata.json'

This doesn't work:

$ cat customer_basedata.json | trdsql -ijq '.entities' 'SELECT id, name FROM -'

Error message:

2022/04/22 14:17:01 import: too many columns on -::jq1

By the way, version 0.9.1 is missing on docker hub :)

Ignores nullable columns

Hello,

Great tool, I was exploring some data, and stumbled upon an issue, when optional columns have been dropped, here is a basic repro case:

$ echo -e '{"method": "GET"}\n{"method": "POST", "meta.user": "with.dot"}' | trdsql "SELECT * FROM -"
"{""method"": ""GET""}"
"{""method"": ""POST"""

is this something expected?

How would I use as Library to output to CSV file?

I'm using trying to use the library. I can select the fields but I can't export it to the CSV file or I do not understand it correctly.

func main() {
	trd := trdsql.NewTRDSQL(
		trdsql.NewImporter(trdsql.InDelimiter(",")),
		trdsql.NewExporter(trdsql.NewWriter()),
	)
	err := trd.Exec("SELECT COUNT(*) FROM sample.csv")
	if err != nil {
		log.Fatal(err)
	}
}

How can I output the result to CSV?

Can't you use the WHERE statement?

func main() {
	jsonString := `
{
  "deviceInfo": {
    "deviceName": "设备3",
    "edgeDeviceName": "设备three",
    "topic": "GG2",
    "encryption": false,
    "compression": false
  },
  "telemetry": {
    "ts": 1585194439000,
    "aa": 6,
    "bb": 10,
    "OPC温度": 10370,
    "OPC湿度": "86",
    "OPC电量": true,
	"staType":0
  }
}
`
	trdsql.EnableDebug()
	r := bytes.NewBufferString(jsonString)
	importer, err := trdsql.NewBufferImporter("test", r, trdsql.InFormat(trdsql.JSON))
	if err != nil {
		log.Fatal(err)
	}
	writer := trdsql.NewWriter(trdsql.OutFormat(trdsql.VF))
	trd := trdsql.NewTRDSQL(importer, trdsql.NewExporter(writer))

	err = trd.Exec("SELECT telemetry FROM test where telemetry.aa > 3")
	if err != nil {
		log.Fatal(err)
	}
}

Out :

2021/10/20 10:54:13 driver: sqlite3, dsn: 
2021/10/20 10:54:13 CREATE TEMPORARY TABLE test ( `deviceInfo` text, `telemetry` text );
2021/10/20 10:54:13 INSERT INTO test (`deviceInfo`, `telemetry`) VALUES (?,?);
2021/10/20 10:54:13 SELECT telemetry FROM test where telemetry.aa > 3
2021/10/20 10:54:13 export: no such column: telemetry.aa [SELECT telemetry FROM test where telemetry.aa > 3]
exit status 1

Want to get Integer values from JSON data instead of exponential notation

About

  • I want to get Integer values from JSON data like CSV parser

Version

% trdsql --version
trdsql version v0.8.0

CSV

data.csv

id,name
1000000,"foo"
1000001,"bar"

Result

  • The results are integer values
% trdsql -icsv -ih "SELECT * FROM data.csv"
1000000,foo
1000001,bar

JSON

data.json

[
  {
    "id": 1000000,
    "name": "foo"
  },
  {
    "id": 1000001,
    "name": "bar"
  }
]

Result

  • The results are exponential notation
    • 1e+06
    • 1.000001e+06
  • I want to get these values as integer
 % trdsql -ijson "SELECT * FROM data.json"
1e+06,foo
1.000001e+06,bar

SQL joins are not reflected in json output

When using the join from the example, the json output is different than the csv output (only the latter is correct)

❯ cat hist.csv
1,2017-7-10
2,2017-7-10
2,2017-7-11%

❯ cat user.csv
1,userA
2,userB%

❯ docker run --rm -it -v $(pwd):/tmp noborus/trdsql "SELECT u.c1,u.c2,h.c2 FROM /tmp/user.csv as u LEFT JOIN /tmp/hist.csv as h ON(u.c1=h.c1)"
1,userA,2017-7-10
2,userB,2017-7-10
2,userB,2017-7-11


❯ docker run --rm -it -v $(pwd):/tmp noborus/trdsql -ojson "SELECT u.c1,u.c2,h.c2 FROM /tmp/user.csv as u LEFT JOIN /tmp/hist.csv as h ON(u.c1=h.c1)"
[
  {
    "c1": "1",
    "c2": "2017-7-10"
  },
  {
    "c1": "2",
    "c2": "2017-7-10"
  },
  {
    "c1": "2",
    "c2": "2017-7-11"
  }
]

multiple files syntax error

Hello, first of all great tool! I use it a lot. If try to work with multiple files I get an error.

$ trdsql -ih -id ";" "SELECT * FROM *csv"
2019/07/31 16:41:55 ERROR: SQL:near "*": syntax error
[SELECT * FROM *csv]

This works fine.

$ trdsql -ih -id ";" "SELECT * FROM file.csv"

Did I something wrong?

Multiple queries

Please support multiple queries. Currently, it seems that only last query is output, e.g.

$ trdsql 'select 1; select 2,3'
2,3

Note: union is not used here because of different number of columns.

A workaround is to run multiple commands (e.g. trdsql 'select 1'; trdsql 'select 2,3'), but database will be created multiple times. And if input is from stdin, you have to save it first to share same input for each command.

Error: Cannot tap noborus/tap: invalid syntax in tap!

==> Tapping noborus/tap
Cloning into '/usr/local/Homebrew/Library/Taps/noborus/homebrew-tap'...
remote: Enumerating objects: 181, done.
remote: Counting objects: 100% (75/75), done.
remote: Compressing objects: 100% (65/65), done.
remote: Total 181 (delta 42), reused 24 (delta 10), pack-reused 106
Receiving objects: 100% (181/181), 27.49 KiB | 5.50 MiB/s, done.
Resolving deltas: 100% (98/98), done.
Error: Invalid formula: /usr/local/Homebrew/Library/Taps/noborus/homebrew-tap/pgsp.rb
pgsp: Calling bottle :unneeded is disabled! There is no replacement.
Please report this issue to the noborus/tap tap (not Homebrew/brew or Homebrew/core):
/usr/local/Homebrew/Library/Taps/noborus/homebrew-tap/pgsp.rb:9

Error: Cannot tap noborus/tap: invalid syntax in tap!

Querying set of CSVs which a lot of entries does not output any json

I am working on a medium-large open data set of Belgian companies, which is freely downloadable at https://kbopub.economie.fgov.be/kbo-open-data/login

I am trying to execute following query to denormalize data into 1 file and it works fine when the output target is CSV, but nothing happens when outputting JSON:

docker run --rm -it -v $(pwd):/tmp noborus/trdsql -ojson -ih " \
SELECT * FROM /tmp/enterprise.csv as e \
LEFT JOIN /tmp/address.csv as a ON (e.EnterpriseNumber=a.EntityNumber) \
LEFT JOIN /tmp/contact.csv as c ON (e.EnterpriseNumber=c.EntityNumber) \
LEFT JOIN /tmp/denomination.csv as d ON (e.EnterpriseNumber=d.EntityNumber) \
";

Any ideas?

build Dockerfile with multi-stage ? It also supports ARM64

this is my dockerfile for test.

But the mirror image is still huge, about 800M

FROM --platform=$BUILDPLATFORM golang:1.16 as builder
ENV TZ=Asia/Shanghai LANG="C.UTF-8"
ARG TARGETARCH
ARG TARGETOS

WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.io,direct

# Copy the go source
COPY query query

# Build
RUN CGO_ENABLED=1 GOOS=$TARGETOS GOARCH=$TARGETARCH go build --tags='json1' -a -o queryd query/cmd/main.go

FROM golang:1.16-buster
WORKDIR /
COPY --from=builder /workspace/queryd .
ENTRYPOINT ["/queryd"]

Specifying column types

Please add an option to auto-detect column types (e.g. -itype), or specify numeric column types (e.g. -inum c2,c3).

Currently, it seems that column types are not auto-detected, which may cause wrong order, e.g.

$ d='a,1
b,2
c,11'

$ <<<$d trdsql -a -
The table name is -.
The file type is CSV.

Data types:
+-------------+------+
| column name | type |
+-------------+------+
| c1          | text |
| c2          | text |
+-------------+------+
…

$ <<<$d trdsql 'select * from - order by c2'
a,1
c,11
b,2

$ <<<$d trdsql 'select * from - order by cast(c2 as number)'
a,1
b,2
c,11

Cannot use the tool, process gets instantly killed with 137 exit code

Even if I run just trdsql -version it exists with a 137 exit code instantly. Any ideas? I'm using 0.10.0 and have installed (and tried to reinstall it already) via Homebrew.

I have used an older version in the past without issues. It's not a memory problem on my computer as I have plenty of RAM available.

~ ❯ trdsql -version                                                                                                                                                                                                        ✘ KILL 05:30:11 PM
[1]    16749 killed     trdsql -version

SQLite "cannot commit - no transaction is active" on large data sets

When a sufficiently large amount of data is passed to trdsql configured to use SQLite, an error is thrown indicating that there is no active transaction to commit.

Here's a demonstration. Although pulling from /dev/urandom, the behavior was consistent. Worked fine for any number less than or equal to 78768, and threw the error for larger numbers. (I would not be surprised if the cutoff number were different in every environment though.)

for byteCnt in 78768 78769
do
	dd if=/dev/urandom bs=$byteCnt count=1 |od -tx1 |sed 's/ /\x0a/g;' |
	trdsql -oat 'select count(*) as RecCnt, c1 as Val from - group by c1 order by count(*) desc limit 5';
done;
1+0 records in
1+0 records out
78768 bytes (79 kB, 77 KiB) copied, 0.0055778 s, 14.1 MB/s
+--------+-----+
| RecCnt | Val |
+--------+-----+
|    353 | a1  |
|    348 |  52 |
|    348 | d8  |
|    347 | 8a  |
|    345 |  81 |
+--------+-----+
1+0 records in
1+0 records out
78769 bytes (79 kB, 77 KiB) copied, 0.0052549 s, 15.0 MB/s
+--------+-----+
| RecCnt | Val |
+--------+-----+
+--------+-----+
2019/10/09 16:26:31 ERROR(COMMIT):cannot commit - no transaction is active

I looked briefly at the relevant code but didn't see anything alarming...

  • trdsql.go: Exec()
  • importer.go: ImportFile()
  • database.go: Import(), insertImport()

Consecutive Tab Delimiters Collapsed To A Single Character

When querying a tab-delimited file, if there's an empty column, the rest of the row shifts over one position. Works fine as long as there is data in every column.

echo 'a,b,c,d 1,2,3,4 5,,,8 9,A,B,C' | sed 's/,/\t/g; s/ /\n/g;' |trdsql -ih -id '\t' -oat 'select * from -'
+---+---+---+---+
| a | b | c | d |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
| 5 | 8 |   |   | <-- value from column "d" is output under column "b"
| 9 | A | B | C |
+---+---+---+---+

For completeness, I tested all the ASCII values 1-126 as delimiters. The problem only occurs for a few values:

  • 9 (Horizontal Tab)
  • 11 (Vertical Tab)
  • 12 (Form Feed)
  • 32 (Space)
for ord in $(seq 1 126)
do
	[ $ord -eq 10 ] && continue; # linefeed
	[ $ord -eq 13 ] && continue; # carriage return
	[ $ord -eq 34 ] && continue; # double quote
	[ $ord -eq 39 ] && continue; # single quote
	[ $ord -eq 49 ] && continue; # the number 1 (our data below)

	delim=$(printf \\$(printf '%03o' $ord));
	[ $ord -eq 92 ] && delim="\\$delim";

	sedDelim=$delim;
	[ "$delim" = "/" ] && sedDelim="\/";
	[ "$delim" = "&" ] && sedDelim="\&";

	output=$(
		echo "1,,1" | sed "s/,/$sedDelim/g;" |
		trdsql -id "$delim" 'select * from -';
	);

	[ "$output" = "1,,1" ] || echo "$output for ord $ord";
done;
1,1 for ord 9
1,1 for ord 11
1,1 for ord 12
1,1 for ord 32

While I've never encountered a file delimited by VT, FF or Space, I regularly encounter tab delimited files, so this is a fairly important issue.

feature request: support input format yaml file

trdsql is awesome tools!!!

Can you add support for yaml files? Sometimes I need to deal with yaml file, and I need other tool to transfer yaml to json file. It would be better if yaml is supported by trdsql directly.

Brew SHA256 Mismatch

Hello,

It seems that the latest version "v0.12.0" released has bad SHA256.

==> Fetching noborus/tap/trdsql
==> Downloading https://github.com/noborus/trdsql/releases/download/v0.12.0/trdsql_v0.12.0_darwin_amd64.zip
==> Downloading from https://objects.githubusercontent.com/github-production-release-asset-2e65be/96136924/ebbecaeb-a282-476d-865b-1654176086d7?X-Amz-Algorith
####################################################################################################################################################### 100.0%
Error: SHA256 mismatch
Expected: fa033118104e50989a52d004e42b0f4eb9936b317dc650322732c254a8b6c9a2
  Actual: 977c8652f8cdd6868d68d25dd84e16f519e8e628c9183937b5cb66dadc840e5a
    File: /Users/aperrier/Library/Caches/Homebrew/downloads/a6ee52ac999d0542717ae953fbfc73793c3d9918136ae950ebfb7aa365bc5eb7--trdsql_v0.12.0_darwin_amd64.zip
To retry an incomplete download, remove the file above.

UTF-8 Byte Order Markers should be ignored

If a data file includes Byte Order Markers (in my case, UTF-8 BOM ef bb bf), those bytes should be ignored by trdsql, but instead are currently treated as part of the data file:

$ trdsql -ih 'select [Service Type] from data.csv limit 1'
2021/05/13 10:37:05 export: no such column: Service Type [select [Service Type] from `data.csv` limit 1]

$ sed -n '1{s/,.*//; p;}' data.csv  | tee >(hexyl)
Service Type
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ ef bb bf 53 65 72 76 69 ┊ 63 65 20 54 79 70 65 0a │×××Servi┊ce Type_│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘

trdsql currently thinks the "Service Type" column name is prefixed with the 3 byte BOM:

$ col=$(printf "%b" '\xef\xbb\xbfService Type'); echo $col | hexyl; trdsql -ih -oat "select [$col] from data.csv limit 1"
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ ef bb bf 53 65 72 76 69 ┊ 63 65 20 54 79 70 65 0a │×××Servi┊ce Type_│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
+--------------------------------+
|          Service Type          |
+--------------------------------+
| Construction - General         |
+--------------------------------+

I don't know if other encodings also have byte order markers, but I see that Go's standard library will apparently never handle BOMs so each application must deal with them individually 😞

"null" representation

Please add options to specify null representation (e.g. -in _, -on _ to use underscores as nulls in input, ouput (in the same way as -id, -od for delimiter)).

It seems that, for output, null and empty string cannot be differentiate; and there is no way to specify null in input.

$ trdsql 'select 1,null,2,"",3'
1,,2,,3

$ echo '1,,2,,3' | trdsql 'select coalesce(c2,"null"),iif(c4=="","empty", c4) from -'
,empty

A workaround is to do it manully, e.g. with coalesce, nullif, but it is tedious to do so for all columns.

$ trdsql 'select 1,coalesce(null, "_"),2,"",3'
1,_,2,,3

$ echo '1,_,2,3' | trdsql 'select coalesce(nullif(c2,"_"), "NULL") from -'
NULL

Standard Deviation

While putting SQL, I need to compute standard deviation of some columns like: "select stddev(c1), stddev(c2) from test.csv"

It displays: ERROR(EXPORT):SQL:no such function: stddev

Not able to use JSON_EXTRACT

Hi,
first of all thank you for this great tool.

I'm trying to use the documentation page to reply JSON_EXTRACT example,
My input is

[
  {
    "id": 1,
    "name": "Drolet",
    "attribute": { "country": "Maldives", "color": "burlywood" }
  },
  {
    "id": 2,
    "name": "Shelly",
    "attribute": { "country": "Yemen", "color": "plum" }
  },
  {
    "id": 3,
    "name": "Tuck",
    "attribute": { "country": "Mayotte", "color": "antiquewhite" }
  }
]

If I run the below command I have nothing.

trdsql -ijson "SELECT id, name, JSON_EXTRACT(attribute,'$country'), JSON_EXTRACT(attribute,'$color') FROM sample2.json"

I'm using trdsql version v0.9.0.

What's wrong in my command?

Thank you

Support shell text utilities for string functions

The sqlite string functions are not powerful.
How about provide a function to use shell utilities like grep, awk, sed etc.?
ex.
trdsql -ih -oh "select shell(grep -oP '[[:digit:]]{5}', c1) as num from d.csv"

Backquotes in output when selecting from table containing dashes

Hardcoded values containing a dash are unexpectedly output with backquotes when selecting from

  • stdin
  • a filename containing one or more dashes

Table data containing dashes is correctly output without any added backquotes.

I can work around it by enclosing my filenames in quotes when selecting directly from them, but that same method does not work to quote stdin.

Some examples:

$ FILE=/tmp/foo-bar.csv  # filename containing a dash
$ echo "x,y-z" > $FILE
$ cat $FILE | trdsql -oat "select '$FILE' as stdin_quoted_dashes, * from -"                                                                                                                                                             
+---------------------+----+-----+
| stdin_quoted_dashes | c1 | c2  |
+---------------------+----+-----+
| /tmp/foo`-`bar.csv  | x  | y-z |
+---------------------+----+-----+

$ trdsql -oat "select '$FILE' as unquoted_file_full_string_quoted, * from $FILE"                                                                                                                                                        
+----------------------------------+----+-----+
| unquoted_file_full_string_quoted | c1 | c2  |
+----------------------------------+----+-----+
| `/tmp/foo-bar.csv`               | x  | y-z |
+----------------------------------+----+-----+

$ trdsql -oat "select '$FILE' as quoted_file_ok, * from \"$FILE\""                                                                                                                                                                      
+------------------+----+-----+
|  quoted_file_ok  | c1 | c2  |
+------------------+----+-----+
| /tmp/foo-bar.csv | x  | y-z |
+------------------+----+-----+

$ # but can't use the same workaround for stdin:(
$ cat $FILE | trdsql -oat "select '$FILE' as quoted_stdin, * from \"-\""                                                                                                                                                                
2019/08/26 08:40:46 ERROR(EXPORT):SQL:no such table: -
[select '/tmp/foo-bar.csv' as quoted_stdin, * from "-"]

$ uname -srvmpio
Linux 4.9.184-linuxkit #1 SMP Tue Jul 2 22:58:16 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ trdsql --version
0.6.3

build error

-GOOS:linux
-GOPACH:amd64
--github.com/mattn/go-sqlite3
github.com\mattn\go-sqlite3\sqlite3_go18.go:18:10: undefined: SQLiteConn
github.com\mattn\go-sqlite3\sqlite3_go18.go:26:10: undefined: SQLiteConn
github.com\mattn\go-sqlite3\sqlite3_go18.go:27:17: undefined: namedValue
github.com\mattn\go-sqlite3\sqlite3_go18.go:29:13: undefined: namedValue
github.com\mattn\go-sqlite3\sqlite3_go18.go:35:10: undefined: SQLiteConn
github.com\mattn\go-sqlite3\sqlite3_go18.go:36:17: undefined: namedValue
github.com\mattn\go-sqlite3\sqlite3_go18.go:44:10: undefined: SQLiteConn
github.com\mattn\go-sqlite3\sqlite3_go18.go:49:10: undefined: SQLiteConn
github.com\mattn\go-sqlite3\sqlite3_go18.go:54:10: undefined: SQLiteStmt
github.com\mattn\go-sqlite3\sqlite3_go18.go:63:10: undefined: SQLiteStmt
github.com\mattn\go-sqlite3\sqlite3_go18.go:36:17: too many errors

Grouping entries with same key inside json output

This one is related to a comment in issue #100

When targetting json, a flat array with objects are returned, but when using joins, it would be interesting to return an array with a list of objects, each containing an array of objects coming from the joined tables.

Example:

❯ docker run --rm -it -v $(pwd):/tmp noborus/trdsql -ojson "SELECT u.c1 as id,u.c2 as name,h.c2 as date FROM /tmp/user.csv as u LEFT JOIN /tmp/hist.csv as h ON(u.c1=h.c1)" > out.json

results in:

❯ cat out.json
[
  {
    "date": "2017-7-10",
    "id": "1",
    "name": "userA"
  },
  {
    "date": "2017-7-10",
    "id": "2",
    "name": "userB"
  },
  {
    "date": "2017-7-11",
    "id": "2",
    "name": "userB"
  }
]

But it would be cool to have the following output, using the filenames or maybe aliases ('h' as alias for 'hist.csv') as object keys for the nested objects:

[
  {
    "date": "2017-7-10",
    "id": "1",
    "name": "userA"
  },
  {
    "id": "2",
    "name": "userB",
    "h": [
      {
        "date": "2017-7-10"
      },
      {
        "date": "2017-7-11"
      }
    ]
  }
]

Having multiple left joins gives more nested objects on the same level as 'h' above.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.