xo / usql

Universal command-line interface for SQL databases
MIT License
8.88k stars 347 forks source link

metadata support database driver layer customization #368

Closed travelliu closed 1 year ago

travelliu commented 2 years ago

Is it possible to change the CatalogSet in medata to interface. It is convenient for different data to display different information. for example

Postgres \l

pg:mogdb@127.0.0.1:5436/postgres=> \l
List of databases
  Catalog
-----------
 mogdb
 mogila
 mysql_b
 oracle
 postgres
 template0
 template1
(7 rows)

want

                         List of databases
  Catalog  | charset |   Collate   |    Ctype    
-----------+---------+-------------+-------------
 mogdb     | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 mogila    | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 mysql_b   | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 oracle    | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 postgres  | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 template0 | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 template1 | UTF8    | en_US.UTF-8 | en_US.UTF-8 
(7 rows)
mg:mogdb@127.0.0.1:5436/postgres=>  

The Result interface exports the values ​​method and CatalogSet allows specifying column names


type Result interface {
    values() []interface{}
}
nineinchnick commented 2 years ago

To add any new fields to CatalogSet they should be common across many databases. Do you know if that's the case for charset and collation?

I'm not sure what do you mean by changing CatalogSet to an interface. It embeds the resultSet that can be used in place of database/sql.Rows

travelliu commented 2 years ago

Demo

medata

type Result interface {
    Values() []interface{}
}

type CatalogSet struct {
    *resultSet
}

func NewCatalogSet(v []Catalog) *CatalogSet {
    r := make([]Result, len(v))
    for i := range v {
        r[i] = &v[i]
    }
    return &CatalogSet{
        resultSet: &resultSet{
            results: r,
            columns: []string{"Catalog"},
        },
    }
}

func NewCatalogSetWithColumns(cols []string) *CatalogSet {
    return &CatalogSet{
        resultSet: &resultSet{
            results: []Result{},
            columns: cols,
        },
    }
}

func (s CatalogSet) AddResult(r Result) {
    s.resultSet.results = append(s.resultSet.results, r)
}

func (s CatalogSet) Get() *Catalog {
    return s.results[s.current-1].(*Catalog)
}

I added mg database driver for testing mg metadata

type Catalog struct {
    Catalog          string
    Charset          string
    DatCompatibility string
    Collate          string
    Ctype            string
}

func (s Catalog) Values() []interface{} {
    return []interface{}{s.Catalog, s.Charset, s.DatCompatibility, s.Collate, s.Ctype}
}

var (
    catalogsColumnName = []string{"Catalog", "Charset", "DatCompatibility", "Collate", "Ctype"}
)

func (r metaReader) Catalogs(metadata.Filter) (*metadata.CatalogSet, error) {
    qstr := `
SELECT d.datname as "Name",
       pg_encoding_to_char(d.encoding) charset,
       datcollate,datctype
FROM pg_catalog.pg_database d`
    rows, closeRows, err := r.query(qstr, []string{}, "1")
    if err != nil {
        return nil, err
    }
    defer closeRows()

    catalogSet := metadata.NewCatalogSetWithColumns(catalogsColumnName)
    for rows.Next() {
        rec := Catalog{}
        err = rows.Scan(&rec.Catalog, &rec.Charset, &rec.Collate, &rec.Ctype)
        if err != nil {
            return nil, err
        }
        catalogSet.AddResult(&rec)
    }
    if rows.Err() != nil {
        return nil, rows.Err()
    }
    return catalogSet, nil
}
go run ./  pg://aaa:mtkOP@123@127.0.0.1:5436/postgres\?sslmode=disable
Connected with driver postgres (PostgreSQL 9.2.4)
Type "help" for help.

pg:aaa@127.0.0.1:5436/postgres=> \l
List of databases
  Catalog  
-----------
 mogdb 
 mogila 
 mysql_b 
 oracle 
 postgres 
 template0 
 template1 
(7 rows)
pg:aaa@127.0.0.1:5436/postgres=> \q

go run ./  mg://aaa:mtkOP@123@127.0.0.1:5436/postgres                
Connected with driver mg (PostgreSQL 3.0.0)
Type "help" for help.

mg:aaa@127.0.0.1:5436/postgres=> \l
                         List of databases
  Catalog  | Charset |   Collate   |    Ctype    
-----------+---------+-------------+-------------
 mogdb     | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 mogila    | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 mysql_b   | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 oracle    | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 postgres  | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 template0 | UTF8    | en_US.UTF-8 | en_US.UTF-8 
 template1 | UTF8    | en_US.UTF-8 | en_US.UTF-8 
(7 rows)
mg:aaa@127.0.0.1:5436/postgres=>  
travelliu commented 2 years ago

should be common across many databases learn. But after all, there will be differences in the information that different databases need to view. It is difficult to do complete unification

nineinchnick commented 2 years ago

If you have a complete code example, can you open a PR? It would be easier to review.

travelliu commented 2 years ago

If you have a complete code example, can you open a PR? It would be easier to review.

OK. I'm done and then I submit PR