Skip to content

Conversation

TheDorkKnight
Copy link

Many applications that are built upon or extended from SQLite are interested in knowing the declared type of columns.

By exposing access to the decltypes of a query result (the SQLiteRows struct), we can add useful capabilities for those who wish to use the SQLite driver directly. These types are already being collected and stored in the SQLiteRows struct, but they are current inaccessible to callers outside of the go-sqlite3 package. Furthermore, decltypes are part of the public sqlite3 API and are not going away anytime soon, so exposing them adds very little risk for maintainability of go-sqlite3.

For those who instead use the database/sql abstraction, the DeclTypes() method would remain unexposed, which is ideal.

Many applications that are built upon or extended from SQLite are interested in knowing the declared type of columns.

By exposing access to the decltypes of a query result (the SQLiteRows struct), we can add useful capabilities for those who wish to use the SQLite driver directly. These types are already being collected and stored in the SQLiteRows struct, but they are current inaccessible to callers outside of the go-sqlite3 package. Furthermore, decltypes are part of the public sqlite3 API and are not going away anytime soon, so exposing them adds very little risk for maintainability of go-sqlite3.

For those who instead use the database/sql abstraction, the DeclTypes() method would remain unexposed, which is ideal.
@TheDorkKnight
Copy link
Author

For my own use case, I'd like to assert the .(*SQLiteRows) type of a driver.Rows returned from a Query(), and then switch behaviour on types from the OGC GeoPackage spec

You might not be interested in having this functionality, but I'll be using it in my own fork and I thought I'd make a pull request just in case.

@mattn
Copy link
Owner

mattn commented Mar 8, 2015

please add test.

On 3/9/15, TheDorkKnight notifications@github.com wrote:

Many applications that are built upon or extended from SQLite are interested
in knowing the declared type of columns.

By exposing access to the decltypes of a query result (the SQLiteRows
struct), we can add useful capabilities for those who wish to use the SQLite
driver directly. These types are already being collected and stored in the
SQLiteRows struct, but they are current inaccessible to callers outside of
the go-sqlite3 package. Furthermore, decltypes are part of the public
sqlite3 API and are not going away anytime soon, so exposing them adds very
little risk for maintainability of go-sqlite3.

For those who instead use the database/sql abstraction, the DeclTypes()
method would remain unexposed, which is ideal.
You can view, comment on, or merge this pull request online at:

#182

-- Commit Summary --

  • Expose column decltypes from SQLiteRows iterator

-- File Changes --

M sqlite3.go (11)

-- Patch Links --

https://github.com/mattn/go-sqlite3/pull/182.patch
https://github.com/mattn/go-sqlite3/pull/182.diff


Reply to this email directly or view it on GitHub:
#182

  • Yasuhiro Matsumoto

Adds new file for tests using ConnectHook pattern
(ie. Get pointer to SQLiteConn with ConnectHook
on sql.Register, open with sql.Open, use methods
from sqlite3 package that are not exposed in
database/sql or database/sql/driver)
@TheDorkKnight
Copy link
Author

test added: 35cee30

I was thinking that the test belonged in a "connection hook" category. I didn't see any tests for the pattern established in _example/hook/hook.go, so I made a new file for that sort of test.

@mattn
Copy link
Owner

mattn commented Mar 9, 2015

Well, I'm thinking you can use pragma table_info. For example

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/mattn/go-sqlite3"
    "log"
)

func main() {
    db, err := sql.Open("sqlite3", "foo.db")
    if err != nil {
        log.Fatal("Failed to open database:", err)
    }
    defer db.Close()

    rows, err := db.Query(`pragma table_info(foo);`)
    if err != nil {
        log.Fatal("Failed to call db.Query:", err)
    }
    defer rows.Close()
    for rows.Next() {
        var cid int
        var name string
        var ctype string
        var notnull int
        var dflt_value *string
        var pk int
        err = rows.Scan(&cid, &name, &ctype, &notnull, &dflt_value, &pk)
        if err != nil {
            log.Fatal("Failed to db.Query:", err)
        }
        fmt.Println(cid, name, ctype, notnull, dflt_value, pk)
    }
}

@TheDorkKnight
Copy link
Author

Quite right; that was how I did my first implementation.

The thing is, the results of a query are not always from a single table (for instance, a JOIN). Moreover, I don't particularly want to be in a position where I have to parse table names out of queries (I'm trying to support executing arbitrary SQL).

The information that I need is nicely served by a compiled statement. Since go-sqlite3 is already gathering and storing decltype information from the statement, for use in interpreting datetimes in SQLiteRows output, I thought that seemed like the most natural and elegant place to gain access.

At any rate, I can just as happily fork, and we can forget the whole idea.

Cheers,
Jake

PS. Just wanted to say, I'm a big fan of your work. I also use go-gtk

@TheDorkKnight TheDorkKnight deleted the expose-column-decltypes branch March 15, 2015 19:02
@ctinkong
Copy link

Well, I'm thinking you can use pragma table_info. For example

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/mattn/go-sqlite3"
    "log"
)

func main() {
    db, err := sql.Open("sqlite3", "foo.db")
    if err != nil {
        log.Fatal("Failed to open database:", err)
    }
    defer db.Close()

    rows, err := db.Query(`pragma table_info(foo);`)
    if err != nil {
        log.Fatal("Failed to call db.Query:", err)
    }
    defer rows.Close()
    for rows.Next() {
        var cid int
        var name string
        var ctype string
        var notnull int
        var dflt_value *string
        var pk int
        err = rows.Scan(&cid, &name, &ctype, &notnull, &dflt_value, &pk)
        if err != nil {
            log.Fatal("Failed to db.Query:", err)
        }
        fmt.Println(cid, name, ctype, notnull, dflt_value, pk)
    }
}

Hi,I have the same question. and I have a try with your code, but it not working.thanks.

@rittneje
Copy link
Collaborator

@ctinkong I'm not exactly sure what you are trying to do, but note that support for fetching the declared type from the result set was added a while ago via the ColumnTypes method. https://pkg.go.dev/database/sql#Rows.ColumnTypes
Be advised that the declared type of a result column is not always available. See https://www.sqlite.org/c3ref/column_decltype.html

If you are still experiencing some problem, please open a new GitHub issue with detailed information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants