Database progress
This commit is contained in:
		
							parent
							
								
									91dd9ce173
								
							
						
					
					
						commit
						15deca0a90
					
				@ -22,6 +22,112 @@ const (
 | 
				
			|||||||
	database_ROUTINE_TYPE_FUNCTION  uint8 = 2
 | 
						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 dbPath string
 | 
				
			||||||
var dbConfig config.Database
 | 
					var dbConfig config.Database
 | 
				
			||||||
var isInit bool
 | 
					var isInit bool
 | 
				
			||||||
@ -40,14 +146,10 @@ func Init() {
 | 
				
			|||||||
	profiler.Register(profiler_DATABASE_QUERY, 4000, "µs")
 | 
						profiler.Register(profiler_DATABASE_QUERY, 4000, "µs")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isInit = true
 | 
						isInit = true
 | 
				
			||||||
	fetchStoredRoutines()
 | 
						initDatabaseStructure()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func connect() {
 | 
					func connect() {
 | 
				
			||||||
	if !isInit {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	log.Printf("Connecting to database %s at %s:%d as %s\n", dbConfig.Database, dbConfig.Host, dbConfig.Port, dbConfig.User)
 | 
						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)
 | 
						fmt.Println(storedRoutines)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -192,9 +295,145 @@ func callStoredProcedure(name string, args ...any) {
 | 
				
			|||||||
		rows.Scan(&res)
 | 
							rows.Scan(&res)
 | 
				
			||||||
		log.Println(res)
 | 
							log.Println(res)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func callStoredFunction(name string, args ...any) {
 | 
					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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user