Commit b91e0a5a authored by gwenn's avatar gwenn

List indexes.

parent a4a86761
...@@ -37,6 +37,7 @@ Meta: ...@@ -37,6 +37,7 @@ Meta:
Conn#Tables Conn#Tables
Conn#Columns Conn#Columns
Conn#ForeignKeys Conn#ForeignKeys
Conn#Indexes/IndexColumns
Time: Time:
JulianDay JulianDay
......
...@@ -32,9 +32,8 @@ func (c *Conn) Databases() (map[string]string, os.Error) { ...@@ -32,9 +32,8 @@ func (c *Conn) Databases() (map[string]string, os.Error) {
var databases map[string]string = make(map[string]string) var databases map[string]string = make(map[string]string)
var ok bool var ok bool
var name, file string var name, file string
var seq int
for ok, err = s.Next(); ok; ok, err = s.Next() { for ok, err = s.Next(); ok; ok, err = s.Next() {
err = s.Scan(&seq, &name, &file) err = s.Scan(nil, &name, &file)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -138,6 +137,59 @@ func (c *Conn) ForeignKeys(table string) (map[int]*ForeignKey, os.Error) { ...@@ -138,6 +137,59 @@ func (c *Conn) ForeignKeys(table string) (map[int]*ForeignKey, os.Error) {
return fks, nil return fks, nil
} }
type Index struct {
Name string
Unique bool
}
// Executes pragma 'index_list'
// TODO How to specify a database-name?
func (c *Conn) Indexes(table string) ([]Index, os.Error) {
s, err := c.Prepare(Mprintf("PRAGMA index_list(%Q)", table))
if err != nil {
return nil, err
}
defer s.Finalize()
var indexes []Index = make([]Index, 0, 5)
var ok bool
for ok, err = s.Next(); ok; ok, err = s.Next() {
i := Index{}
err = s.Scan(nil, &i.Name, &i.Unique)
if err != nil {
return nil, err
}
indexes = append(indexes, i)
}
if err != nil {
return nil, err
}
return indexes, nil
}
// Executes pragma 'index_info'
// Only Column.Cid and Column.Name are specified. All other fields are unspecifed.
func (c *Conn) IndexColumns(index string) ([]Column, os.Error) {
s, err := c.Prepare(Mprintf("PRAGMA index_info(%Q)", index))
if err != nil {
return nil, err
}
defer s.Finalize()
var columns []Column = make([]Column, 0, 5)
var ok bool
for ok, err = s.Next(); ok; ok, err = s.Next() {
c := Column{}
err = s.Scan(nil, &c.Cid, &c.Name)
if err != nil {
return nil, err
}
columns = append(columns, c)
}
if err != nil {
return nil, err
}
return columns, nil
}
// Calls http://sqlite.org/c3ref/mprintf.html // Calls http://sqlite.org/c3ref/mprintf.html
func Mprintf(format string, arg string) string { func Mprintf(format string, arg string) string {
cf := C.CString(format) cf := C.CString(format)
......
...@@ -203,11 +203,13 @@ func (c *Conn) BusyTimeout(ms int) os.Error { ...@@ -203,11 +203,13 @@ func (c *Conn) BusyTimeout(ms int) os.Error {
} }
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, b) // Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, b)
// Another way is PRAGMA foreign_keys = boolean;
// http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html // http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html
func (c *Conn) EnableFKey(b bool) (bool, os.Error) { func (c *Conn) EnableFKey(b bool) (bool, os.Error) {
return c.queryOrSetEnableFKey(btocint(b)) return c.queryOrSetEnableFKey(btocint(b))
} }
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, -1) // Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, -1)
// Another way is PRAGMA foreign_keys;
// http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html // http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html
func (c *Conn) IsFKeyEnabled() (bool, os.Error) { func (c *Conn) IsFKeyEnabled() (bool, os.Error) {
return c.queryOrSetEnableFKey(-1) return c.queryOrSetEnableFKey(-1)
...@@ -623,6 +625,7 @@ func (s *Stmt) NamedScanColumn(name string, value interface{}, nullable bool) (b ...@@ -623,6 +625,7 @@ func (s *Stmt) NamedScanColumn(name string, value interface{}, nullable bool) (b
func (s *Stmt) ScanColumn(index int, value interface{}, nullable bool) (bool, os.Error) { func (s *Stmt) ScanColumn(index int, value interface{}, nullable bool) (bool, os.Error) {
var isNull bool var isNull bool
switch value := value.(type) { switch value := value.(type) {
case nil:
case *string: case *string:
p := C.sqlite3_column_text(s.stmt, C.int(index)) p := C.sqlite3_column_text(s.stmt, C.int(index))
if p == nil { if p == nil {
......
...@@ -53,6 +53,14 @@ func createTable(db *Conn, t *testing.T) { ...@@ -53,6 +53,14 @@ func createTable(db *Conn, t *testing.T) {
} }
} }
func createIndex(db *Conn, t *testing.T) {
err := db.Exec("DROP INDEX IF EXISTS test_index;" +
"CREATE INDEX test_index on test(a_string)")
if err != nil {
t.Fatalf("error creating index: %s", err)
}
}
func TestVersion(t *testing.T) { func TestVersion(t *testing.T) {
v := Version() v := Version()
if !strings.HasPrefix(v, "3") { if !strings.HasPrefix(v, "3") {
...@@ -359,6 +367,40 @@ func TestForeignKeys(t *testing.T) { ...@@ -359,6 +367,40 @@ func TestForeignKeys(t *testing.T) {
} }
} }
func TestIndexes(t *testing.T) {
db := open(t)
defer db.Close()
createTable(db, t)
createIndex(db, t)
indexes, err := db.Indexes("test")
if err != nil {
t.Fatalf("error listing indexes: %s", err)
}
if len(indexes) != 1 {
t.Fatalf("Expected one index <> %d", len(indexes))
}
index := indexes[0]
if index.Name != "test_index" {
t.Errorf("Wrong index name: 'test_index' <> %s", index.Name)
}
if index.Unique {
t.Errorf("Index 'test_index' is not unique")
}
columns, err := db.IndexColumns("test_index")
if err != nil {
t.Fatalf("error listing index columns: %s", err)
}
if len(columns) != 1 {
t.Fatalf("Expected one column <> %d", len(columns))
}
column := columns[0]
if column.Name != "a_string" {
t.Errorf("Wrong column name: 'a_string' <> %s", column.Name)
}
}
func TestBlob(t *testing.T) { func TestBlob(t *testing.T) {
db := open(t) db := open(t)
defer db.Close() defer db.Close()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment