diff --git a/go/dbinfo/dbinfo.go b/go/dbinfo/dbinfo.go index 297272a..8102f75 100644 --- a/go/dbinfo/dbinfo.go +++ b/go/dbinfo/dbinfo.go @@ -20,6 +20,7 @@ import ( "encoding/json" "io" "os" + "sort" "vitess.io/vitess/go/mysql" ) @@ -53,10 +54,30 @@ type TableColumn struct { Extra string `json:"extra,omitempty"` } +type PrimaryKey struct { + Columns []string `json:"columns"` +} + +type Index struct { + Name string + Columns []string `json:"columns"` + NonUnique bool `json:"nonUnique,omitempty"` +} + +type ForeignKey struct { + ColumnName string `json:"columnName"` + ConstraintName string `json:"constraintName"` + ReferencedTableName string `json:"referencedTableName"` + ReferencedColumnName string `json:"referencedColumnName"` +} + type TableInfo struct { - Name string `json:"name"` - Rows int `json:"rows"` - Columns []*TableColumn `json:"columns"` + Name string `json:"name"` + Rows int `json:"rows"` + Columns []*TableColumn `json:"columns"` + PrimaryKey *PrimaryKey `json:"primaryKey,omitempty"` + Indexes []*Index `json:"indexes,omitempty"` + ForeignKeys []*ForeignKey `json:"foreignKeys,omitempty"` } type Info struct { @@ -65,6 +86,80 @@ type Info struct { GlobalVariables map[string]string `json:"globalVariables"` } +func getTableSizes(dbh *DBHelper, tableMap map[string]*TableInfo) error { + ts, err := dbh.getTableSizes() + if err != nil { + return err + } + + for tableName, tableRows := range ts { + ti, ok := tableMap[tableName] + if !ok { + ti = &TableInfo{ + Name: tableName, + } + tableMap[tableName] = ti + } + ti.Rows = tableRows + } + return nil +} + +func getPrimaryKeys(dbh *DBHelper, tableMap map[string]*TableInfo) error { + pks, err := dbh.getPrimaryKeys() + if err != nil { + return err + } + + for tableName, pk := range pks { + ti, ok := tableMap[tableName] + if !ok { + ti = &TableInfo{} + tableMap[tableName] = ti + } + ti.PrimaryKey = &PrimaryKey{ + Columns: pk.columns, + } + } + return nil +} + +func getIndexes(dbh *DBHelper, tableMap map[string]*TableInfo) error { + idxs, err := dbh.getIndexes() + if err != nil { + return err + } + + for tableName, tidx := range idxs { + ti, ok := tableMap[tableName] + if !ok { + ti = &TableInfo{} + tableMap[tableName] = ti + } + for _, idx := range tidx.indexes { + ti.Indexes = append(ti.Indexes, idx) + } + } + return nil +} + +func getForeignKeys(dbh *DBHelper, tableMap map[string]*TableInfo) error { + fks, err := dbh.getForeignKeys() + if err != nil { + return err + } + + for fkName, fk := range fks { + ti, ok := tableMap[fkName] + if !ok { + ti = &TableInfo{} + tableMap[fkName] = ti + } + ti.ForeignKeys = fk + } + return nil +} + func Get(cfg Config) (*Info, error) { vtParams := &mysql.ConnParams{ Host: cfg.VTParams.Host, @@ -74,46 +169,38 @@ func Get(cfg Config) (*Info, error) { DbName: cfg.VTParams.DbName, } + var tableInfo []*TableInfo + tableMap := make(map[string]*TableInfo) + dbh := NewDBHelper(vtParams) - ts, err := dbh.getTableSizes() + + globalVariables, err := dbh.getGlobalVariables() if err != nil { return nil, err } - var tableInfo []*TableInfo - tableMap := make(map[string]*TableInfo) + if err := getTableSizes(dbh, tableMap); err != nil { + return nil, err + } - for tableName, tableRows := range ts { - tableMap[tableName] = &TableInfo{ - Name: tableName, - Rows: tableRows, - } + if err := getPrimaryKeys(dbh, tableMap); err != nil { + return nil, err } - tc, err := dbh.getColumnInfo() - if err != nil { + if err := getIndexes(dbh, tableMap); err != nil { return nil, err } - for tableName, columns := range tc { - ti, ok := tableMap[tableName] - if !ok { - ti = &TableInfo{ - Name: tableName, - } - tableMap[tableName] = ti - } - ti.Columns = columns + if err := getForeignKeys(dbh, tableMap); err != nil { + return nil, err } for tableName := range tableMap { tableInfo = append(tableInfo, tableMap[tableName]) } - - globalVariables, err := dbh.getGlobalVariables() - if err != nil { - return nil, err - } + sort.Slice(tableInfo, func(i, j int) bool { + return tableInfo[i].Name < tableInfo[j].Name + }) dbInfo := &Info{ FileType: "dbinfo", diff --git a/go/dbinfo/dbinfo_test.go b/go/dbinfo/dbinfo_test.go index 5b84091..9fa37d0 100644 --- a/go/dbinfo/dbinfo_test.go +++ b/go/dbinfo/dbinfo_test.go @@ -54,10 +54,11 @@ func TestDBInfoLoad(t *testing.T) { t.Run("validateGlobalVariables", func(t *testing.T) { require.NotEmpty(t, si.GlobalVariables) - require.Len(t, si.GlobalVariables, 3) + require.Len(t, si.GlobalVariables, 4) expected := map[string]string{ "binlog_format": "ROW", "binlog_row_image": "FULL", + "gtid_mode": "OFF", "log_bin": "ON", } require.EqualValues(t, expected, si.GlobalVariables) @@ -144,4 +145,65 @@ func TestDBInfoGet(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, gv) }) + + t.Run("primary keys", func(t *testing.T) { + pks, err := dbh.getPrimaryKeys() + require.NoError(t, err) + require.Len(t, pks, 16) + want := map[string][]string{ + "actor": {"actor_id"}, + "film": {"film_id"}, + "language": {"language_id"}, + "film_category": {"film_id", "category_id"}, + "film_actor": {"actor_id", "film_id"}, + } + for tableName, Columns := range want { + pk, ok := pks[tableName] + require.True(t, ok) + require.Equal(t, Columns, pk.columns) + } + }) + + t.Run("indexes", func(t *testing.T) { + idxs, err := dbh.getIndexes() + require.NoError(t, err) + require.Len(t, idxs, 16) + idx, ok := idxs["film_actor"] + require.True(t, ok) + require.Len(t, idx.indexes, 2) + require.Equal(t, "idx_fk_film_id", idx.indexes["idx_fk_film_id"].Name) + require.Equal(t, []string{"film_id"}, idx.indexes["idx_fk_film_id"].Columns) + idx, ok = idxs["rental"] + require.True(t, ok) + require.Len(t, idx.indexes, 5) + require.Equal(t, "rental_date", idx.indexes["rental_date"].Name) + require.Equal(t, []string{"rental_date", "inventory_id", "customer_id"}, idx.indexes["rental_date"].Columns) + require.Equal(t, "PRIMARY", idx.indexes["PRIMARY_KEY"].Name) + require.Equal(t, []string{"rental_id"}, idx.indexes["PRIMARY_KEY"].Columns) + }) + + t.Run("foreign keys", func(t *testing.T) { + fks, err := dbh.getForeignKeys() + require.NoError(t, err) + require.Len(t, fks, 11) + fk, ok := fks["city"] + require.True(t, ok) + require.Len(t, fk, 1) + require.Equal(t, "country_id", fk[0].ColumnName) + require.Equal(t, "fk_city_country", fk[0].ConstraintName) + require.Equal(t, "country", fk[0].ReferencedTableName) + require.Equal(t, "country_id", fk[0].ReferencedColumnName) + + fk, ok = fks["store"] + require.True(t, ok) + require.Len(t, fk, 2) + require.Equal(t, "address_id", fk[0].ColumnName) + require.Equal(t, "fk_store_address", fk[0].ConstraintName) + require.Equal(t, "address", fk[0].ReferencedTableName) + require.Equal(t, "address_id", fk[0].ReferencedColumnName) + require.Equal(t, "manager_staff_id", fk[1].ColumnName) + require.Equal(t, "fk_store_staff", fk[1].ConstraintName) + require.Equal(t, "staff", fk[1].ReferencedTableName) + require.Equal(t, "staff_id", fk[1].ReferencedColumnName) + }) } diff --git a/go/dbinfo/utils.go b/go/dbinfo/utils.go index 8b23ab9..8255d46 100644 --- a/go/dbinfo/utils.go +++ b/go/dbinfo/utils.go @@ -130,3 +130,106 @@ func (dbh *DBHelper) getGlobalVariables() (map[string]string, error) { } return gv, nil } + +type primaryKey struct { + tableName string + columns []string +} +type primaryKeys map[string]*primaryKey + +func (dbh *DBHelper) getPrimaryKeys() (primaryKeys, error) { + vtConn, cancel, err := dbh.GetConnection() + if err != nil { + return nil, err + } + defer cancel() + + pks := make(primaryKeys) + queryPrimaryKeys := "select table_name, column_name from information_schema.key_column_usage where constraint_name = 'PRIMARY' and table_schema = '%s' order by table_name" + query := fmt.Sprintf(queryPrimaryKeys, dbh.vtParams.DbName) + qr, err := vtConn.ExecuteFetch(query, -1, false) + if err != nil { + return nil, err + } + for _, row := range qr.Rows { + tableName := row[0].ToString() + columnName := row[1].ToString() + pk, ok := pks[tableName] + if !ok { + pk = &primaryKey{tableName: tableName} + pks[tableName] = pk + } + pk.columns = append(pk.columns, columnName) + } + return pks, nil +} + +type tableIndex struct { + tableName string + indexes map[string]*Index +} + +func (dbh *DBHelper) getIndexes() (map[string]*tableIndex, error) { + vtConn, cancel, err := dbh.GetConnection() + if err != nil { + return nil, err + } + defer cancel() + + idxs := make(map[string]*tableIndex) + queryIndexes := "select table_name, index_name, column_name, non_unique from information_schema.statistics where table_schema = '%s' order by table_name, index_name" + query := fmt.Sprintf(queryIndexes, dbh.vtParams.DbName) + qr, err := vtConn.ExecuteFetch(query, -1, false) + if err != nil { + return nil, err + } + for _, row := range qr.Rows { + tableName := row[0].ToString() + indexName := row[1].ToString() + columnName := row[2].ToString() + nonUnique, _ := row[3].ToBool() + tidx, ok := idxs[tableName] + if !ok { + tidx = &tableIndex{tableName: tableName, indexes: make(map[string]*Index)} + idxs[tableName] = tidx + } + idxName := indexName + if idxName == "PRIMARY" { + idxName = "PRIMARY_KEY" + } + idx, ok := tidx.indexes[idxName] + if !ok { + idx = &Index{Name: indexName, NonUnique: nonUnique} + tidx.indexes[idxName] = idx + } + idx.Columns = append(idx.Columns, columnName) + } + return idxs, nil +} + +func (dbh *DBHelper) getForeignKeys() (map[string][]*ForeignKey, error) { + vtConn, cancel, err := dbh.GetConnection() + if err != nil { + return nil, err + } + defer cancel() + + fks := make(map[string][]*ForeignKey) + queryForeignKeys := "select table_name, column_name, constraint_name, referenced_table_name, referenced_column_name from information_schema.key_column_usage where table_schema = '%s' and referenced_table_name is not null" + query := fmt.Sprintf(queryForeignKeys, dbh.vtParams.DbName) + qr, err := vtConn.ExecuteFetch(query, -1, false) + if err != nil { + return nil, err + } + for _, row := range qr.Rows { + tableName := row[0].ToString() + fk := &ForeignKey{ + ColumnName: row[1].ToString(), + ConstraintName: row[2].ToString(), + ReferencedTableName: row[3].ToString(), + ReferencedColumnName: row[4].ToString(), + } + fks[tableName] = append(fks[tableName], fk) + } + return fks, nil +} diff --git a/go/testdata/sakila-dbinfo.json b/go/testdata/sakila-dbinfo.json index decc45c..e7aae7f 100644 --- a/go/testdata/sakila-dbinfo.json +++ b/go/testdata/sakila-dbinfo.json @@ -1,69 +1,49 @@ { "fileType": "dbinfo", - "globalVariables": { - "binlog_format": "ROW", - "binlog_row_image": "FULL", - "log_bin": "ON" - }, "tables": [ { - "name": "inventory", - "rows": 4581, + "name": "actor", + "rows": 200, "columns": [ { - "name": "inventory_id", - "type": "mediumint", - "keyType": "PRI", - "isNullable": false, + "name": "actor_id", + "type": "smallint", + "keyType": "pri", "extra": "auto_increment" }, { - "name": "film_id", - "type": "smallint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "first_name", + "type": "varchar" }, { - "name": "store_id", - "type": "tinyint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "last_name", + "type": "varchar", + "keyType": "mul" }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" } - ] - }, - { - "name": "language", - "rows": 6, - "columns": [ - { - "name": "language_id", - "type": "tinyint", - "keyType": "PRI", - "isNullable": false, - "extra": "auto_increment" - }, - { - "name": "name", - "type": "char", - "keyType": "", - "isNullable": false, - "extra": "" - }, - { - "name": "last_update", - "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + ], + "primaryKey": { + "columns": [ + "actor_id" + ] + }, + "indexes": [ + { + "Name": "idx_actor_last_name", + "columns": [ + "last_name" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "actor_id" + ] } ] }, @@ -73,120 +53,192 @@ "columns": [ { "name": "actor_id", - "type": "smallint", - "keyType": "", - "isNullable": false, - "extra": "" + "type": "smallint" }, { "name": "first_name", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "type": "varchar" }, { "name": "last_name", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "type": "varchar" }, { "name": "film_info", "type": "text", - "keyType": "", - "isNullable": true, - "extra": "" + "isNullable": true } ] }, { - "name": "staff_list", - "rows": 0, + "name": "address", + "rows": 603, "columns": [ { - "name": "ID", - "type": "tinyint", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "address_id", + "type": "smallint", + "keyType": "pri", + "extra": "auto_increment" }, { - "name": "name", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "address", + "type": "varchar" }, { - "name": "address", + "name": "address2", "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "isNullable": true }, { - "name": "zip code", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "district", + "type": "varchar" }, { - "name": "phone", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "city_id", + "type": "smallint", + "keyType": "mul" }, { - "name": "city", + "name": "postal_code", "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "isNullable": true }, { - "name": "country", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "phone", + "type": "varchar" }, { - "name": "SID", + "name": "location", + "type": "geometry", + "keyType": "mul" + }, + { + "name": "last_update", + "type": "timestamp", + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "address_id" + ] + }, + "indexes": [ + { + "Name": "PRIMARY", + "columns": [ + "address_id" + ] + }, + { + "Name": "idx_fk_city_id", + "columns": [ + "city_id" + ], + "nonUnique": true + }, + { + "Name": "idx_location", + "columns": [ + "location" + ], + "nonUnique": true + } + ], + "foreignKeys": [ + { + "columnName": "city_id", + "constraintName": "fk_address_city", + "referencedTableName": "city", + "referencedColumnName": "city_id" + } + ] + }, + { + "name": "category", + "rows": 16, + "columns": [ + { + "name": "category_id", "type": "tinyint", - "keyType": "", - "isNullable": false, - "extra": "" + "keyType": "pri", + "extra": "auto_increment" + }, + { + "name": "name", + "type": "varchar" + }, + { + "name": "last_update", + "type": "timestamp", + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "category_id" + ] + }, + "indexes": [ + { + "Name": "PRIMARY", + "columns": [ + "category_id" + ] } ] }, { - "name": "film_text", - "rows": 1000, + "name": "city", + "rows": 600, "columns": [ { - "name": "film_id", + "name": "city_id", "type": "smallint", - "keyType": "PRI", - "isNullable": false, - "extra": "" + "keyType": "pri", + "extra": "auto_increment" }, { - "name": "title", - "type": "varchar", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "city", + "type": "varchar" }, { - "name": "description", - "type": "text", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "country_id", + "type": "smallint", + "keyType": "mul" + }, + { + "name": "last_update", + "type": "timestamp", + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "city_id" + ] + }, + "indexes": [ + { + "Name": "idx_fk_country_id", + "columns": [ + "country_id" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "city_id" + ] + } + ], + "foreignKeys": [ + { + "columnName": "country_id", + "constraintName": "fk_city_country", + "referencedTableName": "country", + "referencedColumnName": "country_id" } ] }, @@ -197,332 +249,290 @@ { "name": "country_id", "type": "smallint", - "keyType": "PRI", - "isNullable": false, + "keyType": "pri", "extra": "auto_increment" }, { "name": "country", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "type": "varchar" }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "country_id" + ] + }, + "indexes": [ + { + "Name": "PRIMARY", + "columns": [ + "country_id" + ] } ] }, { - "name": "nicer_but_slower_film_list", - "rows": 0, + "name": "customer", + "rows": 599, "columns": [ { - "name": "FID", + "name": "customer_id", "type": "smallint", - "keyType": "", - "isNullable": false, - "extra": "" + "keyType": "pri", + "extra": "auto_increment" }, { - "name": "title", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "store_id", + "type": "tinyint", + "keyType": "mul" }, { - "name": "description", - "type": "text", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "first_name", + "type": "varchar" }, { - "name": "category", + "name": "last_name", "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "keyType": "mul" }, { - "name": "price", - "type": "decimal", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "email", + "type": "varchar", + "isNullable": true }, { - "name": "length", + "name": "address_id", "type": "smallint", - "keyType": "", - "isNullable": true, - "extra": "" + "keyType": "mul" }, { - "name": "rating", - "type": "enum", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "active", + "type": "tinyint" }, { - "name": "actors", - "type": "text", - "keyType": "", + "name": "create_date", + "type": "datetime" + }, + { + "name": "last_update", + "type": "timestamp", "isNullable": true, - "extra": "" + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "customer_id" + ] + }, + "indexes": [ + { + "Name": "idx_fk_store_id", + "columns": [ + "store_id" + ], + "nonUnique": true + }, + { + "Name": "idx_last_name", + "columns": [ + "last_name" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "customer_id" + ] + }, + { + "Name": "idx_fk_address_id", + "columns": [ + "address_id" + ], + "nonUnique": true + } + ], + "foreignKeys": [ + { + "columnName": "address_id", + "constraintName": "fk_customer_address", + "referencedTableName": "address", + "referencedColumnName": "address_id" + }, + { + "columnName": "store_id", + "constraintName": "fk_customer_store", + "referencedTableName": "store", + "referencedColumnName": "store_id" } ] }, { - "name": "film_list", + "name": "customer_list", "rows": 0, "columns": [ { - "name": "FID", - "type": "smallint", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "ID", + "type": "smallint" }, { - "name": "title", + "name": "name", "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "isNullable": true }, { - "name": "description", - "type": "text", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "address", + "type": "varchar" }, { - "name": "category", + "name": "zip code", "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "isNullable": true }, { - "name": "price", - "type": "decimal", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "phone", + "type": "varchar" }, { - "name": "length", - "type": "smallint", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "city", + "type": "varchar" }, { - "name": "rating", - "type": "enum", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "country", + "type": "varchar" }, { - "name": "actors", - "type": "text", - "keyType": "", - "isNullable": true, - "extra": "" - } - ] - }, - { - "name": "sales_by_film_category", - "rows": 0, - "columns": [ - { - "name": "category", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "notes", + "type": "varchar" }, { - "name": "total_sales", - "type": "decimal", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "SID", + "type": "tinyint" } ] }, { - "name": "payment", - "rows": 16086, + "name": "film", + "rows": 1000, "columns": [ { - "name": "payment_id", + "name": "film_id", "type": "smallint", - "keyType": "PRI", - "isNullable": false, + "keyType": "pri", "extra": "auto_increment" }, { - "name": "customer_id", - "type": "smallint", - "keyType": "MUL", - "isNullable": false, - "extra": "" - }, - { - "name": "staff_id", - "type": "tinyint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "title", + "type": "varchar", + "keyType": "mul" }, { - "name": "rental_id", - "type": "int", - "keyType": "MUL", - "isNullable": true, - "extra": "" + "name": "description", + "type": "text", + "isNullable": true }, { - "name": "amount", - "type": "decimal", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "release_year", + "type": "year", + "isNullable": true }, { - "name": "payment_date", - "type": "datetime", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "language_id", + "type": "tinyint", + "keyType": "mul" }, { - "name": "last_update", - "type": "timestamp", - "keyType": "", - "isNullable": true, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" - } - ] - }, - { - "name": "staff", - "rows": 2, - "columns": [ - { - "name": "staff_id", + "name": "original_language_id", "type": "tinyint", - "keyType": "PRI", - "isNullable": false, - "extra": "auto_increment" + "keyType": "mul", + "isNullable": true }, { - "name": "first_name", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "rental_duration", + "type": "tinyint" }, { - "name": "last_name", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "rental_rate", + "type": "decimal" }, { - "name": "address_id", + "name": "length", "type": "smallint", - "keyType": "MUL", - "isNullable": false, - "extra": "" - }, - { - "name": "picture", - "type": "blob", - "keyType": "", - "isNullable": true, - "extra": "" + "isNullable": true }, { - "name": "email", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" - }, - { - "name": "store_id", - "type": "tinyint", - "keyType": "MUL", - "isNullable": false, - "extra": "" - }, - { - "name": "active", - "type": "tinyint", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "replacement_cost", + "type": "decimal" }, { - "name": "username", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "rating", + "type": "enum", + "isNullable": true }, { - "name": "password", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "special_features", + "type": "set", + "isNullable": true }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" } - ] - }, - { - "name": "film_category", - "rows": 1000, - "columns": [ - { - "name": "film_id", - "type": "smallint", - "keyType": "PRI", - "isNullable": false, - "extra": "" - }, + ], + "primaryKey": { + "columns": [ + "film_id" + ] + }, + "indexes": [ + { + "Name": "idx_fk_language_id", + "columns": [ + "language_id" + ], + "nonUnique": true + }, + { + "Name": "idx_fk_original_language_id", + "columns": [ + "original_language_id" + ], + "nonUnique": true + }, + { + "Name": "idx_title", + "columns": [ + "title" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "film_id" + ] + } + ], + "foreignKeys": [ { - "name": "category_id", - "type": "tinyint", - "keyType": "PRI", - "isNullable": false, - "extra": "" + "columnName": "language_id", + "constraintName": "fk_film_language", + "referencedTableName": "language", + "referencedColumnName": "language_id" }, { - "name": "last_update", - "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "columnName": "original_language_id", + "constraintName": "fk_film_language_original", + "referencedTableName": "language", + "referencedColumnName": "language_id" } ] }, @@ -533,283 +543,437 @@ { "name": "actor_id", "type": "smallint", - "keyType": "PRI", - "isNullable": false, - "extra": "" + "keyType": "pri" }, { "name": "film_id", "type": "smallint", - "keyType": "PRI", - "isNullable": false, - "extra": "" + "keyType": "pri" }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "actor_id", + "film_id" + ] + }, + "indexes": [ + { + "Name": "idx_fk_film_id", + "columns": [ + "film_id" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "actor_id", + "film_id" + ] + } + ], + "foreignKeys": [ + { + "columnName": "actor_id", + "constraintName": "fk_film_actor_actor", + "referencedTableName": "actor", + "referencedColumnName": "actor_id" + }, + { + "columnName": "film_id", + "constraintName": "fk_film_actor_film", + "referencedTableName": "film", + "referencedColumnName": "film_id" } ] }, { - "name": "city", - "rows": 600, + "name": "film_category", + "rows": 1000, "columns": [ { - "name": "city_id", + "name": "film_id", "type": "smallint", - "keyType": "PRI", - "isNullable": false, - "extra": "auto_increment" + "keyType": "pri" }, { - "name": "city", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" - }, - { - "name": "country_id", - "type": "smallint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "category_id", + "type": "tinyint", + "keyType": "pri" }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "film_id", + "category_id" + ] + }, + "indexes": [ + { + "Name": "fk_film_category_category", + "columns": [ + "category_id" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "film_id", + "category_id" + ] + } + ], + "foreignKeys": [ + { + "columnName": "category_id", + "constraintName": "fk_film_category_category", + "referencedTableName": "category", + "referencedColumnName": "category_id" + }, + { + "columnName": "film_id", + "constraintName": "fk_film_category_film", + "referencedTableName": "film", + "referencedColumnName": "film_id" } ] }, { - "name": "customer_list", + "name": "film_list", "rows": 0, "columns": [ { - "name": "ID", - "type": "smallint", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "FID", + "type": "smallint" }, { - "name": "name", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "title", + "type": "varchar" }, { - "name": "address", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "description", + "type": "text", + "isNullable": true }, { - "name": "zip code", + "name": "category", "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "isNullable": true }, { - "name": "phone", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "price", + "type": "decimal" }, { - "name": "city", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "length", + "type": "smallint", + "isNullable": true }, { - "name": "country", + "name": "rating", + "type": "enum", + "isNullable": true + }, + { + "name": "actors", + "type": "text", + "isNullable": true + } + ] + }, + { + "name": "film_text", + "rows": 1000, + "columns": [ + { + "name": "film_id", + "type": "smallint", + "keyType": "pri" + }, + { + "name": "title", "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "keyType": "mul" + }, + { + "name": "description", + "type": "text", + "isNullable": true + } + ], + "primaryKey": { + "columns": [ + "film_id" + ] + }, + "indexes": [ + { + "Name": "PRIMARY", + "columns": [ + "film_id" + ] + }, + { + "Name": "idx_title_description", + "columns": [ + "title", + "description" + ], + "nonUnique": true + } + ] + }, + { + "name": "inventory", + "rows": 4581, + "columns": [ + { + "name": "inventory_id", + "type": "mediumint", + "keyType": "pri", + "extra": "auto_increment" }, { - "name": "notes", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "film_id", + "type": "smallint", + "keyType": "mul" }, { - "name": "SID", + "name": "store_id", "type": "tinyint", - "keyType": "", - "isNullable": false, - "extra": "" - } - ] - }, - { - "name": "sales_by_store", - "rows": 0, - "columns": [ - { - "name": "store", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "keyType": "mul" }, { - "name": "manager", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "last_update", + "type": "timestamp", + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "inventory_id" + ] + }, + "indexes": [ + { + "Name": "idx_fk_film_id", + "columns": [ + "film_id" + ], + "nonUnique": true + }, + { + "Name": "idx_store_id_film_id", + "columns": [ + "store_id", + "film_id" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "inventory_id" + ] + } + ], + "foreignKeys": [ + { + "columnName": "film_id", + "constraintName": "fk_inventory_film", + "referencedTableName": "film", + "referencedColumnName": "film_id" }, { - "name": "total_sales", - "type": "decimal", - "keyType": "", - "isNullable": true, - "extra": "" + "columnName": "store_id", + "constraintName": "fk_inventory_store", + "referencedTableName": "store", + "referencedColumnName": "store_id" } ] }, { - "name": "category", - "rows": 16, + "name": "language", + "rows": 6, "columns": [ { - "name": "category_id", + "name": "language_id", "type": "tinyint", - "keyType": "PRI", - "isNullable": false, + "keyType": "pri", "extra": "auto_increment" }, { "name": "name", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "type": "char" }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "language_id" + ] + }, + "indexes": [ + { + "Name": "PRIMARY", + "columns": [ + "language_id" + ] } ] }, { - "name": "customer", - "rows": 599, + "name": "nicer_but_slower_film_list", + "rows": 0, "columns": [ { - "name": "customer_id", - "type": "smallint", - "keyType": "PRI", - "isNullable": false, - "extra": "auto_increment" + "name": "FID", + "type": "smallint" }, { - "name": "store_id", - "type": "tinyint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "title", + "type": "varchar" }, { - "name": "first_name", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "description", + "type": "text", + "isNullable": true }, { - "name": "last_name", + "name": "category", "type": "varchar", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "isNullable": true }, { - "name": "email", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "price", + "type": "decimal" }, { - "name": "address_id", + "name": "length", "type": "smallint", - "keyType": "MUL", - "isNullable": false, - "extra": "" - }, - { - "name": "active", - "type": "tinyint", - "keyType": "", - "isNullable": false, - "extra": "" + "isNullable": true }, { - "name": "create_date", - "type": "datetime", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "rating", + "type": "enum", + "isNullable": true }, { - "name": "last_update", - "type": "timestamp", - "keyType": "", - "isNullable": true, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "name": "actors", + "type": "text", + "isNullable": true } ] }, { - "name": "actor", - "rows": 200, + "name": "payment", + "rows": 16086, "columns": [ { - "name": "actor_id", + "name": "payment_id", "type": "smallint", - "keyType": "PRI", - "isNullable": false, + "keyType": "pri", "extra": "auto_increment" }, { - "name": "first_name", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "customer_id", + "type": "smallint", + "keyType": "mul" }, { - "name": "last_name", - "type": "varchar", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "staff_id", + "type": "tinyint", + "keyType": "mul" + }, + { + "name": "rental_id", + "type": "int", + "keyType": "mul", + "isNullable": true + }, + { + "name": "amount", + "type": "decimal" + }, + { + "name": "payment_date", + "type": "datetime" }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "isNullable": true, + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "payment_id" + ] + }, + "indexes": [ + { + "Name": "idx_fk_staff_id", + "columns": [ + "staff_id" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "payment_id" + ] + }, + { + "Name": "fk_payment_rental", + "columns": [ + "rental_id" + ], + "nonUnique": true + }, + { + "Name": "idx_fk_customer_id", + "columns": [ + "customer_id" + ], + "nonUnique": true + } + ], + "foreignKeys": [ + { + "columnName": "customer_id", + "constraintName": "fk_payment_customer", + "referencedTableName": "customer", + "referencedColumnName": "customer_id" + }, + { + "columnName": "rental_id", + "constraintName": "fk_payment_rental", + "referencedTableName": "rental", + "referencedColumnName": "rental_id" + }, + { + "columnName": "staff_id", + "constraintName": "fk_payment_staff", + "referencedTableName": "staff", + "referencedColumnName": "staff_id" } ] }, @@ -820,253 +984,350 @@ { "name": "rental_id", "type": "int", - "keyType": "PRI", - "isNullable": false, + "keyType": "pri", "extra": "auto_increment" }, { "name": "rental_date", "type": "datetime", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "keyType": "mul" }, { "name": "inventory_id", "type": "mediumint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "keyType": "mul" }, { "name": "customer_id", "type": "smallint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "keyType": "mul" }, { "name": "return_date", "type": "datetime", - "keyType": "", - "isNullable": true, - "extra": "" + "isNullable": true }, { "name": "staff_id", "type": "tinyint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "keyType": "mul" }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "rental_id" + ] + }, + "indexes": [ + { + "Name": "rental_date", + "columns": [ + "rental_date", + "inventory_id", + "customer_id" + ] + }, + { + "Name": "idx_fk_customer_id", + "columns": [ + "customer_id" + ], + "nonUnique": true + }, + { + "Name": "idx_fk_inventory_id", + "columns": [ + "inventory_id" + ], + "nonUnique": true + }, + { + "Name": "idx_fk_staff_id", + "columns": [ + "staff_id" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "rental_id" + ] + } + ], + "foreignKeys": [ + { + "columnName": "customer_id", + "constraintName": "fk_rental_customer", + "referencedTableName": "customer", + "referencedColumnName": "customer_id" + }, + { + "columnName": "inventory_id", + "constraintName": "fk_rental_inventory", + "referencedTableName": "inventory", + "referencedColumnName": "inventory_id" + }, + { + "columnName": "staff_id", + "constraintName": "fk_rental_staff", + "referencedTableName": "staff", + "referencedColumnName": "staff_id" } ] }, { - "name": "store", - "rows": 2, + "name": "sales_by_film_category", + "rows": 0, "columns": [ { - "name": "store_id", - "type": "tinyint", - "keyType": "PRI", - "isNullable": false, - "extra": "auto_increment" + "name": "category", + "type": "varchar" }, { - "name": "manager_staff_id", - "type": "tinyint", - "keyType": "UNI", - "isNullable": false, - "extra": "" + "name": "total_sales", + "type": "decimal", + "isNullable": true + } + ] + }, + { + "name": "sales_by_store", + "rows": 0, + "columns": [ + { + "name": "store", + "type": "varchar", + "isNullable": true }, { - "name": "address_id", - "type": "smallint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "manager", + "type": "varchar", + "isNullable": true }, { - "name": "last_update", - "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "name": "total_sales", + "type": "decimal", + "isNullable": true } ] }, { - "name": "address", - "rows": 603, + "name": "staff", + "rows": 2, "columns": [ { - "name": "address_id", - "type": "smallint", - "keyType": "PRI", - "isNullable": false, + "name": "staff_id", + "type": "tinyint", + "keyType": "pri", "extra": "auto_increment" }, { - "name": "address", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "first_name", + "type": "varchar" }, { - "name": "address2", - "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "last_name", + "type": "varchar" }, { - "name": "district", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "address_id", + "type": "smallint", + "keyType": "mul" }, { - "name": "city_id", - "type": "smallint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "picture", + "type": "blob", + "isNullable": true }, { - "name": "postal_code", + "name": "email", "type": "varchar", - "keyType": "", - "isNullable": true, - "extra": "" + "isNullable": true }, { - "name": "phone", - "type": "varchar", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "store_id", + "type": "tinyint", + "keyType": "mul" }, { - "name": "location", - "type": "geometry", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "active", + "type": "tinyint" + }, + { + "name": "username", + "type": "varchar" + }, + { + "name": "password", + "type": "varchar", + "isNullable": true }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "staff_id" + ] + }, + "indexes": [ + { + "Name": "idx_fk_address_id", + "columns": [ + "address_id" + ], + "nonUnique": true + }, + { + "Name": "idx_fk_store_id", + "columns": [ + "store_id" + ], + "nonUnique": true + }, + { + "Name": "PRIMARY", + "columns": [ + "staff_id" + ] + } + ], + "foreignKeys": [ + { + "columnName": "address_id", + "constraintName": "fk_staff_address", + "referencedTableName": "address", + "referencedColumnName": "address_id" + }, + { + "columnName": "store_id", + "constraintName": "fk_staff_store", + "referencedTableName": "store", + "referencedColumnName": "store_id" } ] }, { - "name": "film", - "rows": 1000, + "name": "staff_list", + "rows": 0, "columns": [ { - "name": "film_id", - "type": "smallint", - "keyType": "PRI", - "isNullable": false, - "extra": "auto_increment" + "name": "ID", + "type": "tinyint" }, { - "name": "title", + "name": "name", "type": "varchar", - "keyType": "MUL", - "isNullable": false, - "extra": "" - }, - { - "name": "description", - "type": "text", - "keyType": "", - "isNullable": true, - "extra": "" + "isNullable": true }, { - "name": "release_year", - "type": "year", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "address", + "type": "varchar" }, { - "name": "language_id", - "type": "tinyint", - "keyType": "MUL", - "isNullable": false, - "extra": "" + "name": "zip code", + "type": "varchar", + "isNullable": true }, { - "name": "original_language_id", - "type": "tinyint", - "keyType": "MUL", - "isNullable": true, - "extra": "" + "name": "phone", + "type": "varchar" }, { - "name": "rental_duration", - "type": "tinyint", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "city", + "type": "varchar" }, { - "name": "rental_rate", - "type": "decimal", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "country", + "type": "varchar" }, { - "name": "length", - "type": "smallint", - "keyType": "", - "isNullable": true, - "extra": "" - }, + "name": "SID", + "type": "tinyint" + } + ] + }, + { + "name": "store", + "rows": 2, + "columns": [ { - "name": "replacement_cost", - "type": "decimal", - "keyType": "", - "isNullable": false, - "extra": "" + "name": "store_id", + "type": "tinyint", + "keyType": "pri", + "extra": "auto_increment" }, { - "name": "rating", - "type": "enum", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "manager_staff_id", + "type": "tinyint", + "keyType": "uni" }, { - "name": "special_features", - "type": "set", - "keyType": "", - "isNullable": true, - "extra": "" + "name": "address_id", + "type": "smallint", + "keyType": "mul" }, { "name": "last_update", "type": "timestamp", - "keyType": "", - "isNullable": false, - "extra": "DEFAULT_GENERATED on update CURRENT_TIMESTAMP" + "extra": "default_generated on update current_timestamp" + } + ], + "primaryKey": { + "columns": [ + "store_id" + ] + }, + "indexes": [ + { + "Name": "idx_fk_address_id", + "columns": [ + "address_id" + ], + "nonUnique": true + }, + { + "Name": "idx_unique_manager", + "columns": [ + "manager_staff_id" + ] + }, + { + "Name": "PRIMARY", + "columns": [ + "store_id" + ] + } + ], + "foreignKeys": [ + { + "columnName": "address_id", + "constraintName": "fk_store_address", + "referencedTableName": "address", + "referencedColumnName": "address_id" + }, + { + "columnName": "manager_staff_id", + "constraintName": "fk_store_staff", + "referencedTableName": "staff", + "referencedColumnName": "staff_id" } ] } - ] + ], + "globalVariables": { + "binlog_format": "ROW", + "binlog_row_image": "FULL", + "gtid_mode": "OFF", + "log_bin": "ON" + } } \ No newline at end of file