mattn / mattn/go-sqlite3

SQLiteRows.Columns() returns outdated state

Open
#1,284 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
9.2k
Forks
1.2k
Avg merge
19m
Merged PRs (30d)
4

Description

This is a little difficult to explain so I apologize if it seems confusing.

The problem is that when there 2+ live connections and 1 of the connection changes the schema, calling rows.Columns() from any of the other connections return an outdated list of columns (aka. the state before the schema change).

Below is a minimal reproducible:

package main

import (
	"database/sql"
	"log"
	"os"

	_ "github.com/mattn/go-sqlite3"
	// note: uncomment to test with the pure go port (the driver name is "sqlite")
	// _ "modernc.org/sqlite"
)

func main() {
	os.Remove("./foo.db")

	db1, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db1.Close()

	db2, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db2.Close()

	// ensure that there is a live db1 connection
	if err = db1.Ping(); err != nil {
		log.Println("failed to ensure db1 live connection", err)
		return
	}

	// create the dummy schema
	_, err = db1.Exec("CREATE TABLE foo (id INTEGER PRIMARY KEY, title TEXT)")
	if err != nil {
		log.Println("create table failure:", err)
		return
	}

	// ensure that there is a live db2 connection AFTER the table creation
	if err = db2.Ping(); err != nil {
		log.Println("failed to ensure db2 live connection", err)
		return
	}

	// rename for example the column through one of the connections
	_, err = db1.Exec("ALTER TABLE foo RENAME COLUMN title TO title_new")
	if err != nil {
		log.Println("column rename failure:", err)
		return
	}

	// apparently running PRAGMA quick_check, optimize, etc. seems to fix the sync state
	// db2.Exec("PRAGMA quick_check")

	rows, err := db2.Query("select * from foo")
	if err != nil {
		log.Println("select failure:", err)
		return
	}
	defer rows.Close()

	columns, _ := rows.Columns()

	log.Println("Expected [id, title_new], got", columns)
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the minimal Go reproduction using the go-sqlite3 driver, then start at database/sql Query and Rows.Columns behavior and trace the driver's handling of schema changes across live connections. Done means the reproduced query returns [id, title_new] from the second connection after the first connection renames the column, with regression coverage for that scenario.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, sqlite
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.