Database progress
parent
91dd9ce173
commit
15deca0a90
|
@ -22,6 +22,112 @@ const (
|
|||
database_ROUTINE_TYPE_FUNCTION uint8 = 2
|
||||
)
|
||||
|
||||
type databaseEnumIndexType string
|
||||
|
||||
const (
|
||||
database_ENUM_INDEX_PRIMARY databaseEnumIndexType = "PRIMARY"
|
||||
database_ENUM_INDEX_UNIQUE databaseEnumIndexType = "UNIQUE"
|
||||
)
|
||||
|
||||
type columsDefinition struct {
|
||||
Name string
|
||||
Type string
|
||||
Default any
|
||||
IsNullable bool
|
||||
Extra string
|
||||
Charset any
|
||||
Collation any
|
||||
Table string
|
||||
}
|
||||
|
||||
type indexDefinition struct {
|
||||
Type databaseEnumIndexType
|
||||
Name string
|
||||
Table string
|
||||
Columns []string
|
||||
}
|
||||
|
||||
type foreignKeyDefinition struct {
|
||||
Name string
|
||||
Table string
|
||||
ColumnName string
|
||||
PointingToTable string
|
||||
PointingToColumn string
|
||||
UpdateRule string
|
||||
DeleteRule string
|
||||
}
|
||||
|
||||
type tableDefinition struct {
|
||||
Name string
|
||||
Columns []columsDefinition
|
||||
}
|
||||
|
||||
type databaseDefinition struct {
|
||||
Name string
|
||||
Tables []tableDefinition
|
||||
Indexes []indexDefinition
|
||||
ForeignKeys []foreignKeyDefinition
|
||||
}
|
||||
|
||||
var listTables = []tableDefinition{
|
||||
{
|
||||
Name: "users",
|
||||
Columns: []columsDefinition{
|
||||
{
|
||||
Name: "id",
|
||||
Type: "int(11)",
|
||||
Default: nil,
|
||||
IsNullable: false,
|
||||
Extra: "AUTO_INCREMENT",
|
||||
},
|
||||
{
|
||||
Name: "name",
|
||||
Type: "varchar(256)",
|
||||
Default: nil,
|
||||
IsNullable: false,
|
||||
Extra: "",
|
||||
Charset: "utf8mb4",
|
||||
Collation: "utf8mb4_unicode_ci",
|
||||
},
|
||||
{
|
||||
Name: "password",
|
||||
Type: "varchar(256)",
|
||||
Default: nil,
|
||||
IsNullable: false,
|
||||
Extra: "",
|
||||
Charset: "utf8mb4",
|
||||
Collation: "utf8mb4_unicode",
|
||||
},
|
||||
{
|
||||
Name: "password-salt",
|
||||
Type: "varchar(256)",
|
||||
Default: nil,
|
||||
IsNullable: false,
|
||||
Extra: "",
|
||||
Charset: "utf8mb4",
|
||||
Collation: "utf8mb4_unicode",
|
||||
},
|
||||
{
|
||||
Name: "permission_level",
|
||||
Type: "enum('ADMIN', 'MODERATOR', 'USER')",
|
||||
Default: "USER",
|
||||
IsNullable: false,
|
||||
Extra: "",
|
||||
Charset: nil,
|
||||
},
|
||||
{
|
||||
Name: "email",
|
||||
Type: "varchar(256)",
|
||||
Default: nil,
|
||||
IsNullable: true,
|
||||
Extra: "",
|
||||
Charset: "utf8mb4",
|
||||
Collation: "utf8mb4_unicode",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var dbPath string
|
||||
var dbConfig config.Database
|
||||
var isInit bool
|
||||
|
@ -40,14 +146,10 @@ func Init() {
|
|||
profiler.Register(profiler_DATABASE_QUERY, 4000, "µs")
|
||||
|
||||
isInit = true
|
||||
fetchStoredRoutines()
|
||||
initDatabaseStructure()
|
||||
}
|
||||
|
||||
func connect() {
|
||||
if !isInit {
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
log.Printf("Connecting to database %s at %s:%d as %s\n", dbConfig.Database, dbConfig.Host, dbConfig.Port, dbConfig.User)
|
||||
|
||||
|
@ -170,6 +272,7 @@ func fetchStoredRoutines() {
|
|||
}
|
||||
}
|
||||
}
|
||||
fmt.Print("ROUTINES : ")
|
||||
fmt.Println(storedRoutines)
|
||||
}
|
||||
|
||||
|
@ -192,9 +295,145 @@ func callStoredProcedure(name string, args ...any) {
|
|||
rows.Scan(&res)
|
||||
log.Println(res)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func callStoredFunction(name string, args ...any) {
|
||||
var query string
|
||||
if len(args) == 0 {
|
||||
query = fmt.Sprintf("SELECT %s()", name)
|
||||
} else if len(args) == 1 {
|
||||
query = fmt.Sprintf("SELECT %s(?)", name)
|
||||
} else {
|
||||
query = strings.Repeat(", ?", len(args)-1)
|
||||
query = fmt.Sprintf("SELECT %s(?%s)", name, query)
|
||||
}
|
||||
|
||||
var rows *sql.Rows = executeQuery(query, args...)
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var res string
|
||||
rows.Scan(&res)
|
||||
log.Println(res)
|
||||
}
|
||||
}
|
||||
|
||||
func fetchTables() []string {
|
||||
var query string = fmt.Sprintf("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=\"%s\";", dbConfig.Database)
|
||||
var rows *sql.Rows = executeQuery(query)
|
||||
var tables []string = make([]string, 0)
|
||||
if rows != nil {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var resName string
|
||||
rows.Scan(&resName)
|
||||
tables = append(tables, resName)
|
||||
}
|
||||
}
|
||||
return tables
|
||||
}
|
||||
|
||||
func fetchColumns(table string) []columsDefinition {
|
||||
var query string = fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT, IS_NULLABLE, EXTRA, CHARACTER_SET_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=\"%s\" AND TABLE_NAME=\"%s\";", dbConfig.Database, table)
|
||||
var rows *sql.Rows = executeQuery(query)
|
||||
var columns []columsDefinition = make([]columsDefinition, 0)
|
||||
if rows != nil {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var resName, resType, resDefault, resNullable, resExtra, resCharset, resCollation string
|
||||
rows.Scan(&resName, &resType, &resDefault, &resNullable, &resExtra, &resCharset, &resCollation)
|
||||
columns = append(columns, columsDefinition{
|
||||
Name: resName,
|
||||
Type: resType,
|
||||
Default: resDefault,
|
||||
IsNullable: resNullable == "YES",
|
||||
Extra: resExtra,
|
||||
Charset: resCharset,
|
||||
Collation: resCollation,
|
||||
Table: table,
|
||||
})
|
||||
}
|
||||
}
|
||||
return columns
|
||||
}
|
||||
|
||||
func fetchIndexes() []indexDefinition {
|
||||
// SELECT * FROM STATISTICS as S INNER JOIN TABLE_CONSTRAINTS as TC ON TC.TABLE_SCHEMA = S.TABLE_SCHEMA AND TC.CONSTRAINT_NAME = S.INDEX_NAME AND TC.TABLE_NAME = S.TABLE_NAME WHERE S.TABLE_SCHEMA = "RPG";
|
||||
// SELECT S.COLUMN_NAME as COLUMN_NAME, S.INDEX_NAME AS INDEX_NAME, TC.CONSTRAINT_TYPE AS CONSTRAINT_TYPE FROM STATISTICS as S INNER JOIN TABLE_CONSTRAINTS as TC ON TC.TABLE_SCHEMA = S.TABLE_SCHEMA AND TC.CONSTRAINT_NAME = S.INDEX_NAME AND TC.TABLE_NAME = S.TABLE_NAME WHERE S.TABLE_SCHEMA = "RPG" AND S.TABLE_NAME = "folders" AND TC.CONSTRAINT_TYPE IN("UNIQUE", "PRIMARY KEY");
|
||||
|
||||
// Add PRIMARY : ALTER TABLE <table> ADD CONSTRAINT PRIMARY KEY(<columns>);
|
||||
// Add UNIQUE : ALTER TABLE <table> ADD CONSTRAINT <constraint_name> UNIQUE(<columns>);
|
||||
|
||||
var query string = fmt.Sprintf("SELECT S.COLUMN_NAME as COLUMN_NAME, S.INDEX_NAME AS INDEX_NAME, TC.CONSTRAINT_TYPE AS CONSTRAINT_TYPE, S.TABLE_NAME AS TABLE_NAME FROM information_schema.STATISTICS as S INNER JOIN information_schema.TABLE_CONSTRAINTS as TC ON TC.TABLE_SCHEMA = S.TABLE_SCHEMA AND TC.CONSTRAINT_NAME = S.INDEX_NAME AND TC.TABLE_NAME = S.TABLE_NAME WHERE S.TABLE_SCHEMA = \"%s\" AND TC.CONSTRAINT_TYPE IN(\"UNIQUE\", \"PRIMARY KEY\");", dbConfig.Database)
|
||||
fmt.Println(query)
|
||||
var rows *sql.Rows = executeQuery(query)
|
||||
var indexes []indexDefinition = make([]indexDefinition, 0)
|
||||
if rows != nil {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var resColumn, resIndex, resType, resTable string
|
||||
rows.Scan(&resColumn, &resIndex, &resType, &resTable)
|
||||
var index indexDefinition = indexDefinition{
|
||||
Table: resTable,
|
||||
Name: resIndex,
|
||||
Type: database_ENUM_INDEX_PRIMARY,
|
||||
Columns: []string{resColumn},
|
||||
}
|
||||
if resType == "UNIQUE" {
|
||||
index.Type = database_ENUM_INDEX_UNIQUE
|
||||
}
|
||||
indexes = append(indexes, index)
|
||||
}
|
||||
}
|
||||
return indexes
|
||||
}
|
||||
|
||||
func fetchForeignKeys() []foreignKeyDefinition {
|
||||
|
||||
// ADD ALTER TABLE <table> ADD CONSTRAINT <constraint_name> FOREIGN KEY(<column>) REFERENCES <ref_table>(<ref_column>) ON DELETE <CASCADE / SET NULL> UPDATE <CASCADE / SET NULL>;
|
||||
|
||||
// SELECT RC.CONSTRAINT_NAME as CONTRAINT_NAME, KCU.TABLE_NAME, KCU.COLUMN_NAME, KCU.REFERENCED_TABLE_NAME, KCU.REFERENCED_COLUMN_NAME, RC.UPDATE_RULE, RC.DELETE_RULE FROM REFERENTIAL_CONSTRAINTS AS RC INNER JOIN KEY_COLUMN_USAGE AS KCU ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = "RPG";
|
||||
var query string = fmt.Sprintf("SELECT INDEX_NAME, COLUMN_NAME FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=\"%s\";", dbConfig.Database)
|
||||
var rows *sql.Rows = executeQuery(query)
|
||||
var fk []foreignKeyDefinition = make([]foreignKeyDefinition, 0)
|
||||
if rows != nil {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var resName string
|
||||
rows.Scan(&resName)
|
||||
fk = append(fk, foreignKeyDefinition{
|
||||
Name: resName,
|
||||
})
|
||||
}
|
||||
}
|
||||
return fk
|
||||
}
|
||||
|
||||
func initDatabaseStructure() {
|
||||
fetchStoredRoutines()
|
||||
fetchIndexes()
|
||||
fetchForeignKeys()
|
||||
|
||||
var tables []string = fetchTables()
|
||||
|
||||
for i := range tables {
|
||||
var columns []columsDefinition = fetchColumns(tables[i])
|
||||
fmt.Printf("Table %s : \n", tables[i])
|
||||
for j := range columns {
|
||||
fmt.Printf(" - Column %s %s IsNullable:%t Default:%s Extra:%s Charset:%s/%s\n",
|
||||
columns[j].Name, columns[j].Type, columns[j].IsNullable, columns[j].Default, columns[j].Extra, columns[j].Charset, columns[j].Collation)
|
||||
}
|
||||
}
|
||||
|
||||
var indexes []indexDefinition = fetchIndexes()
|
||||
|
||||
for i := range indexes {
|
||||
fmt.Printf("Index %s : \n", indexes[i])
|
||||
}
|
||||
|
||||
var fk []foreignKeyDefinition = fetchForeignKeys()
|
||||
|
||||
for i := range fk {
|
||||
fmt.Printf("Foreign key %s : \n", fk[i])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue