diff --git a/src/database/database.go b/src/database/database.go index 107dabf..dff5e9e 100644 --- a/src/database/database.go +++ b/src/database/database.go @@ -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