{"id":26455058,"url":"https://github.com/sionpixley/inquiry","last_synced_at":"2026-05-11T09:18:29.672Z","repository":{"id":281929294,"uuid":"945615440","full_name":"sionpixley/inquiry","owner":"sionpixley","description":"Inquiry is a Go package that converts a CSV file into an in-memory SQLite database, allowing you to run SQL statements on the CSV file.","archived":false,"fork":false,"pushed_at":"2025-03-11T22:26:25.000Z","size":10,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-11T22:28:20.637Z","etag":null,"topics":["csv","go","golang","golang-library","golang-package"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sionpixley.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-09T20:31:31.000Z","updated_at":"2025-03-11T22:26:28.000Z","dependencies_parsed_at":"2025-03-11T22:38:26.290Z","dependency_job_id":null,"html_url":"https://github.com/sionpixley/inquiry","commit_stats":null,"previous_names":["sionpixley/inquiry"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sionpixley%2Finquiry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sionpixley%2Finquiry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sionpixley%2Finquiry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sionpixley%2Finquiry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sionpixley","download_url":"https://codeload.github.com/sionpixley/inquiry/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244300905,"owners_count":20430835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csv","go","golang","golang-library","golang-package"],"created_at":"2025-03-18T20:29:49.403Z","updated_at":"2026-05-11T09:18:29.667Z","avatar_url":"https://github.com/sionpixley.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Inquiry\n\nInquiry is a Go package that converts CSV files into a SQLite database, allowing you to run SQL statements on them.\n\n## Table of contents\n\n1. [How to install](#how-to-install)\n2. [How to use](#how-to-use)\n    1. [Defining your struct](#defining-your-struct)\n        1. [Go field to SQLite column mapping](#go-field-to-sqlite-column-mapping)\n    2. [Creating an in-memory SQLite database from a CSV file](#creating-an-in-memory-sqlite-database-from-a-csv-file)\n        1. [Without options](#without-options)\n        2. [With options](#with-options)\n    3. [Creating a new table from a CSV file and adding it to an existing SQLite database](#creating-a-new-table-from-a-csv-file-and-adding-it-to-an-existing-sqlite-database)\n        1. [Adding a table to an in-memory database from a CSV](#adding-a-table-to-an-in-memory-database-from-a-csv)\n        2. [Adding a table to an on-disk database from a CSV](#adding-a-table-to-an-on-disk-database-from-a-csv)\n3. [Contributing](#contributing)\n\n## How to install\n\n`go get github.com/sionpixley/inquiry`\n\n## How to use\n\nUsing Inquiry is pretty simple: You \"connect\" to the CSV file and Inquiry will return a `*sql.DB` and an `error`. You can then use the returned `*sql.DB` to do any operations that you would normally do with a SQLite database.\n\nYou can also create new tables from CSV files and add them to an existing SQLite database (in-memory or not).\n\n### Defining your struct\n\nInquiry uses generics and package `reflect` to build the SQLite database/table and to insert the data. Please put the struct fields in the same position as the column they are supposed to represent in the CSV file. Different struct definitions yield different SQL `CREATE TABLE` statements. For example:\n\n```go\ntype Student struct {\n    Id         int\n    FirstName  string\n    MiddleName *string\n    LastName   string\n    IsFullTime bool\n    GPA        float64\n}\n```\n\n```sql\n-- SQL CREATE TABLE statement that is generated from the above Go struct definition.\nCREATE TABLE 'Student'(\n    'Id'         INTEGER NOT NULL,\n    'FirstName'  TEXT NOT NULL,\n    'MiddleName' TEXT NULL,\n    'LastName'   TEXT NOT NULL,\n    'IsFullTime' INTEGER NOT NULL CHECK('IsFullTime' IN (0,1)),\n    'GPA'        REAL NOT NULL\n);\n```\n\nPlease consult the table below for a full list of which Go field types map to which SQLite column types.\n\n#### Go field to SQLite column mapping\n\n| Go Field Type | SQLite Column Type |\n| ------------- | --------------- |\n| `bool` | `INTEGER NOT NULL CHECK(\u003cfield_name\u003e IN (0,1))` |\n| `*bool` | `INTEGER NULL CHECK(\u003cfield_name\u003e IN (0,1))` |\n| - `float32` \u003cbr\u003e - `float64` | `REAL NOT NULL` |\n| - `*float32` \u003cbr\u003e - `*float64` | `REAL NULL` |\n| - `int` \u003cbr\u003e - `int8` \u003cbr\u003e - `int16` \u003cbr\u003e - `int32` \u003cbr\u003e - `int64` | `INTEGER NOT NULL` |\n| - `*int` \u003cbr\u003e - `*int8` \u003cbr\u003e - `*int16` \u003cbr\u003e - `*int32` \u003cbr\u003e - `*int64` | `INTEGER NULL` |\n| `string` | `TEXT NOT NULL` |\n| `*string` | `TEXT NULL` |\n\nOn nullable columns, certain values in the CSV will insert a `NULL` into the database. These values are: an empty value, `null`, and `NULL`. On non-nullable columns, these values can potentially throw an error or be inserted as they are (especially in the case of a `TEXT` column).\n\n#### Inquiry struct tags\n\nYou can use struct tags to create primary keys, indexes, and unique constraints.\n\n\u003e **Note:** Inquiry currently only supports single-column indexes and unique constraints.\n\n```go\ntype Customer struct {\n    Index            int    `inquiry:\"primaryKey\"`\n    CustomerId       string `inquiry:\"unique\"`\n    FirstName        string\n    LastName         string\n    Company          string\n    City             string\n    Country          string\n    Phone1           string\n    Phone2           string\n    Email            *string\n    SubscriptionDate string\n    Website          string `inquiry:\"index\"`\n}\n```\n\n```sql\n-- SQL that is generated from the above Go struct definition.\nCREATE TABLE 'Customer'(\n    'Index'            INTEGER NOT NULL,\n    'CustomerId'       TEXT NOT NULL,\n    'FirstName'        TEXT NOT NULL,\n    'LastName'         TEXT NOT NULL,\n    'Company'          TEXT NOT NULL,\n    'City'             TEXT NOT NULL,\n    'Country'          TEXT NOT NULL,\n    'Phone1'           TEXT NOT NULL,\n    'Phone2'           TEXT NOT NULL,\n    'Email'            TEXT NULL,\n    'SubscriptionDate' TEXT NOT NULL,\n    'Website'          TEXT NOT NULL,\n\n    CONSTRAINT PK_Customer_Index PRIMARY KEY('Index'),\n    CONSTRAINT Unique_Customer_CustomerId UNIQUE('CustomerId')\n);\n\nCREATE INDEX NonClustered_Customer_Website ON 'Customer'('Website');\n```\n\n### Creating an in-memory SQLite database from a CSV file\n\nTo create an in-memory database from a CSV file, use the `Connect` or `ConnectWithOptions` function. \n\nWith options, you can specify your CSV delimiter and whether the file has a header row or not. If you don't provide options, Inquiry will default the delimiter to a comma and assume there is no header row.\n\n#### Without options\n\n```\n// example.csv\n\n1,hi,2.8\n2,hello,3.4\n3,yo,90.3\n4,happy,100.5\n5,yay,8.1\n```\n\n```go\n// main.go\n\npackage main\n\nimport (\n    \"fmt\"\n    \"log\"\n\n    \"github.com/sionpixley/inquiry/pkg/inquiry\"\n)\n\ntype Example struct {\n    Id    int\n    Name  string\n    Value float64\n}\n\nfunc main() {\n    db, err := inquiry.Connect[Example](\"example.csv\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n    // Don't forget to close the database.\n    defer db.Close()\n\n    rows, err := db.Query(\"SELECT * FROM Example WHERE Value \u003e 80 ORDER BY Name ASC;\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n    defer rows.Close()\n\n    for rows.Next() {\n        var example Example\n        err = rows.Scan(\u0026example.Id, \u0026example.Name, \u0026example.Value)\n        if err != nil {\n            log.Fatalln(err)\n        }\n        fmt.Printf(\"%d %s %f\", example.Id, example.Name, example.Value)\n        fmt.Println()\n    }\n}\n```\n\n```\n// output\n\n4 happy 100.500000\n3 yo 90.300000\n```\n\n#### With options\n\nThe options are set using a struct: `CsvOptions`. Please see below for the definition of the `CsvOptions` struct and an example of using it.\n\n```go\ntype CsvOptions struct {\n    CommentCharacter rune `json:\"commentCharacter\"`\n    Delimiter        rune `json:\"delimiter\"`\n    HasHeaderRow     bool `json:\"hasHeaderRow\"`\n    TrimLeadingSpace bool `json:\"trimLeadingSpace\"`\n    UseLazyQuotes    bool `json:\"useLazyQuotes\"`\n}\n```\n\n```\n// example.csv\n\nId|Name|Value\n1|hi|2.8\n2|hello|3.4\n3|yo|90.3\n4|happy|100.5\n5|yay|8.1\n```\n\n```go\n// main.go\n\npackage main\n\nimport (\n    \"fmt\"\n    \"log\"\n\n    \"github.com/sionpixley/inquiry/pkg/inquiry\"\n)\n\ntype Example struct {\n    Id    int\n    Name  string\n    Value float64\n}\n\nfunc main() {\n    options := inquiry.CsvOptions{\n        Delimiter:    '|',\n        HasHeaderRow: true,\n    }\n    \n    db, err := inquiry.ConnectWithOptions[Example](\"example.csv\", options)\n    if err != nil {\n        log.Fatalln(err)\n    }\n    // Don't forget to close the database.\n    defer db.Close()\n\n    rows, err := db.Query(\"SELECT * FROM Example WHERE Value \u003e 80 ORDER BY Name ASC;\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n    defer rows.Close()\n\n    for rows.Next() {\n        var example Example\n        err = rows.Scan(\u0026example.Id, \u0026example.Name, \u0026example.Value)\n        if err != nil {\n            log.Fatalln(err)\n        }\n        fmt.Printf(\"%d %s %f\", example.Id, example.Name, example.Value)\n        fmt.Println()\n    }\n}\n```\n\n```\n// output\n\n4 happy 100.500000\n3 yo 90.300000\n```\n\n### Creating a new table from a CSV file and adding it to an existing SQLite database\n\nTo create a new table from a CSV file and add it to an existing SQLite database, use the `CreateTable` or `CreateTableWithOptions` function.\n\nWith options, you can specify your CSV delimiter and whether the file has a header row or not. If you don't provide options, Inquiry will default the delimiter to a comma and assume there is no header row.\n\nThis works on in-memory databases as well as databases that persist to disk.\n\n#### Adding a table to an in-memory database from a CSV\n\n```\n// example.csv\n\nId|Name|Value\n1|hi|2.8\n2|hello|3.4\n3|yo|90.3\n4|happy|100.5\n5|yay|8.1\n```\n\n```\n// test.csv\n\n1,this is a horrible test\n2,ehhh\n```\n\n```go\n// main.go\n\npackage main\n\nimport (\n    \"fmt\"\n    \"log\"\n\n    \"github.com/sionpixley/inquiry/pkg/inquiry\"\n)\n\ntype Example struct {\n    Id    int\n    Name  string\n    Value float64\n}\n\ntype Test struct {\n    Id  int\n    Val string\n}\n\nfunc main() {\n    options := inquiry.CsvOptions{\n        Delimiter:    '|',\n        HasHeaderRow: true,\n    }\n    \n    db, err := inquiry.ConnectWithOptions[Example](\"example.csv\", options)\n    if err != nil {\n        log.Fatalln(err)\n    }\n    // Don't forget to close the database.\n    defer db.Close()\n    \n    err = inquiry.CreateTable[Test](db, \"test.csv\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n\n    rows, err := db.Query(\"SELECT * FROM Example WHERE Value \u003e 80 ORDER BY Name ASC;\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n    defer rows.Close()\n\n    for rows.Next() {\n        var example Example\n        err = rows.Scan(\u0026example.Id, \u0026example.Name, \u0026example.Value)\n        if err != nil {\n            log.Fatalln(err)\n        }\n        fmt.Printf(\"%d %s %f\", example.Id, example.Name, example.Value)\n        fmt.Println()\n    }\n\n    rows, err = db.Query(\"SELECT * FROM Test ORDER BY Id DESC;\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n    defer rows.Close()\n\n    for rows.Next() {\n        var test Test\n        err = rows.Scan(\u0026test.Id, \u0026test.Val)\n        if err != nil {\n            log.Fatalln(err)\n        }\n        fmt.Printf(\"%d %s\", test.Id, test.Val)\n        fmt.Println()\n    }\n}\n```\n\n```\n// output\n\n4 happy 100.500000\n3 yo 90.300000\n2 ehhh\n1 this is a horrible test\n```\n\n#### Adding a table to an on-disk database from a CSV\n\n```\n// example.db is an on-disk database with data equivalent to:\n\n1,hi,2.8\n2,hello,3.4\n3,yo,90.3\n4,happy,100.5\n5,yay,8.1\n```\n\n```\n// test.csv\n\n1;this is a horrible test\n2;ehhh\n```\n\n```go\n// main.go\n\npackage main\n\nimport (\n    \"database/sql\"\n    \"fmt\"\n    \"log\"\n\n    _ \"github.com/mattn/go-sqlite3\"\n    \"github.com/sionpixley/inquiry/pkg/inquiry\"\n)\n\ntype Example struct {\n    Id    int\n    Name  string\n    Value float64\n}\n\ntype Test struct {\n    Id  int\n    Val string\n}\n\nfunc main() {\n    db, err := sql.Open(\"sqlite3\", \"example.db\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n    // Don't forget to close the database.\n    defer db.Close()\n\n    options := inquiry.CsvOptions{\n        Delimiter:    ';',\n        HasHeaderRow: false,\n    }\n    \n    err = inquiry.CreateTableWithOptions[Test](db, \"test.csv\", options)\n    if err != nil {\n        log.Fatalln(err)\n    }\n\n    rows, err := db.Query(\"SELECT * FROM Example WHERE Value \u003e 80 ORDER BY Name ASC;\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n    defer rows.Close()\n\n    for rows.Next() {\n        var example Example\n        err = rows.Scan(\u0026example.Id, \u0026example.Name, \u0026example.Value)\n        if err != nil {\n            log.Fatalln(err)\n        }\n        fmt.Printf(\"%d %s %f\", example.Id, example.Name, example.Value)\n        fmt.Println()\n    }\n\n    rows, err = db.Query(\"SELECT * FROM Test ORDER BY Id DESC;\")\n    if err != nil {\n        log.Fatalln(err)\n    }\n    defer rows.Close()\n\n    for rows.Next() {\n        var test Test\n        err = rows.Scan(\u0026test.Id, \u0026test.Val)\n        if err != nil {\n            log.Fatalln(err)\n        }\n        fmt.Printf(\"%d %s\", test.Id, test.Val)\n        fmt.Println()\n    }\n}\n```\n\n```\n// output\n\n4 happy 100.500000\n3 yo 90.300000\n2 ehhh\n1 this is a horrible test\n```\n\n## Contributing\n\nAll contributions are welcome! If you wish to contribute to the project, the best way would be forking this repo and making a pull request from your fork with all of your suggested changes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsionpixley%2Finquiry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsionpixley%2Finquiry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsionpixley%2Finquiry/lists"}