Documentation
¶
Index ¶
- Variables
- func AdaptNamedParams(dialect, statement string, variables map[string]any, unsafe ...bool) (string, []any, error)
- func AdaptPlaceholdersToDialect(query *string, dialect string)
- func AddChangesTrigger(tableName string, dbName ...string) error
- func AddDashStats(fn ...StatsFunc)
- func AddTrigger(onTable, col, bf_af_UpdateInsertDelete string, stmt string, dbName ...string)
- func AllowTerminalCommands(commands ...string)
- func AutoMigrate[T any](tableName string, dbName ...string) error
- func Benchmark(f func(), name string, iterations int)
- func ClearDBTraces()
- func DebugNodeManager()
- func DifferenceBetweenSlices[T comparable](slice1 []T, slice2 []T) []T
- func DisableCache()
- func DisableTracing()
- func DisallowTerminalCommands(commands ...string)
- func DownloadFile(filepath string, url string) error
- func DropTrigger(tableName, column string, dbName ...string)
- func Exec(dbName, query string, args ...any) error
- func ExecContext(ctx context.Context, dbName, query string, args ...any) error
- func ExecContextNamed(ctx context.Context, query string, args map[string]any, dbName ...string) error
- func ExecNamed(query string, args map[string]any, dbName ...string) error
- func FlushCache(tables ...string)
- func GenerateUUID() string
- func GetAllColumnsTypes(table string, dbName ...string) (map[string]string, []string)
- func GetAllTables(dbName ...string) []string
- func GetConnection(dbName ...string) *sql.DB
- func GetDatabaseSize(dbName string) (string, error)
- func GetMemoryTableAndDB(tbName string, dbName ...string) (TableEntity, DatabaseEntity, error)
- func GetTotalRequests() uint64
- func In(query string, args ...any) (string, []any)
- func InitShell() bool
- func IsValidEmail(email string) bool
- func JSON_ARRAY(values []any, as string, dialect ...string) string
- func JSON_CAST(value string, as string, dialect ...string) string
- func JSON_EXTRACT(dataJson string, opt ...JsonOption) string
- func JSON_OBJECT(values []any, as string, dialect ...string) string
- func JSON_REMOVE(dataJson string, opt ...JsonOption) string
- func JSON_SET(dataJson string, opt ...JsonOption) string
- func LinkModel[T any](to_table_name string, dbName ...string)
- func LogQueries()
- func ManyToMany(table1, table2 string, dbName ...string) error
- func New(dbType Dialect, dbName string, dbDriver driver.Driver, dbDSN ...string) error
- func OnDelete(fn HookFunc)
- func OnDrop(fn HookFunc)
- func OnInsert(fn HookFunc)
- func OnSet(fn HookFunc)
- func PrintSystemMetrics()
- func RemoveFromSlice[T comparable](slice *[]T, elemsToRemove ...T)
- func ResetStruct(input interface{}) error
- func RunEvery(t time.Duration, fn func(cancelChan chan struct{}))
- func SetAdminPath(path string)
- func SetCacheMaxMemory(megaByte int)
- func SetMaxDBTraces(max int)
- func Shutdown(dbNames ...string) error
- func SliceContains[T comparable](elems []T, vs ...T) bool
- func SliceToString(slice interface{}) string
- func StorageSize(dbName string) float64
- func Transaction(dbName ...string) (*sql.Tx, error)
- func UnsafeNamedQuery(query string, args map[string]any) (string, error)
- func WithBus(config ...ksmux.Config) *kactor.BusServer
- func WithDashboard(addr string, options ...DashOpts) *kactor.BusServer
- func WithDocs(generateJsonDocs bool, outJsonDocs string, ...) *kactor.BusServer
- func WithEmbededDocs(embeded embed.FS, embededDirPath string, ...) *kactor.BusServer
- func WithMetrics(httpHandler http.Handler) *kactor.BusServer
- func WithPprof(path ...string) *kactor.BusServer
- func WithSchemaCheck()
- func WithShell()
- func WithTracing()
- func Wrap(driver driver.Driver, hooks Hooks) driver.Driver
- func WrapConn(conn driver.Conn, hooks Hooks) driver.Conn
- type BuilderM
- func (b *BuilderM) AddRelated(relatedTable string, whereRelatedTable string, whereRelatedArgs ...any) (int, error)
- func (b *BuilderM) All() ([]map[string]any, error)
- func (b *BuilderM) BulkInsert(rowsData ...map[string]any) ([]int, error)
- func (b *BuilderM) Context(ctx context.Context) *BuilderM
- func (b *BuilderM) Database(dbName string) *BuilderM
- func (b *BuilderM) Debug() *BuilderM
- func (b *BuilderM) Delete() (int, error)
- func (b *BuilderM) DeleteRelated(relatedTable string, whereRelatedTable string, whereRelatedArgs ...any) (int, error)
- func (b *BuilderM) Drop() (int, error)
- func (b *BuilderM) GetRelated(relatedTable string, dest *[]map[string]any) error
- func (b *BuilderM) Insert(rowData map[string]any) (int, error)
- func (b *BuilderM) InsertR(rowData map[string]any) (map[string]any, error)
- func (b *BuilderM) JoinRelated(relatedTable string, dest *[]map[string]any) error
- func (b *BuilderM) Limit(limit int) *BuilderM
- func (b *BuilderM) NoCache() *BuilderM
- func (b *BuilderM) One() (map[string]any, error)
- func (b *BuilderM) OrderBy(fields ...string) *BuilderM
- func (b *BuilderM) Page(pageNumber int) *BuilderM
- func (b *BuilderM) QueryM(statement string, args ...any) ([]map[string]any, error)
- func (b *BuilderM) QueryMNamed(statement string, args map[string]any, unsafe ...bool) ([]map[string]any, error)
- func (b *BuilderM) Select(columns ...string) *BuilderM
- func (b *BuilderM) Set(query string, args ...any) (int, error)
- func (b *BuilderM) SetM(data map[string]any) (int, error)
- func (b *BuilderM) Trace() *BuilderM
- func (b *BuilderM) Where(query string, args ...any) *BuilderM
- func (b *BuilderM) WhereNamed(query string, args map[string]any) *BuilderM
- type BuilderS
- func (b *BuilderS[T]) AddRelated(relatedTable string, whereRelatedTable string, whereRelatedArgs ...any) (int, error)
- func (b *BuilderS[T]) All() ([]T, error)
- func (b *BuilderS[T]) BulkInsert(models ...*T) ([]int, error)
- func (b *BuilderS[T]) Context(ctx context.Context) *BuilderS[T]
- func (b *BuilderS[T]) Database(dbName string) *BuilderS[T]
- func (b *BuilderS[T]) Debug() *BuilderS[T]
- func (b *BuilderS[T]) Delete() (int, error)
- func (b *BuilderS[T]) DeleteRelated(relatedTable string, whereRelatedTable string, whereRelatedArgs ...any) (int, error)
- func (b *BuilderS[T]) Drop() (int, error)
- func (b *BuilderS[T]) GetRelated(relatedTable string, dest any) error
- func (b *BuilderS[T]) Insert(model *T) (int, error)
- func (b *BuilderS[T]) InsertR(model *T) (T, error)
- func (b *BuilderS[T]) JoinRelated(relatedTable string, dest any) error
- func (b *BuilderS[T]) Limit(limit int) *BuilderS[T]
- func (b *BuilderS[T]) NoCache() *BuilderS[T]
- func (b *BuilderS[T]) One() (T, error)
- func (b *BuilderS[T]) OrderBy(fields ...string) *BuilderS[T]
- func (b *BuilderS[T]) Page(pageNumber int) *BuilderS[T]
- func (b *BuilderS[T]) QueryS(statement string, args ...any) ([]T, error)
- func (b *BuilderS[T]) QuerySNamed(statement string, args map[string]any, unsafe ...bool) ([]T, error)
- func (b *BuilderS[T]) Select(columns ...string) *BuilderS[T]
- func (b *BuilderS[T]) Set(query string, args ...any) (int, error)
- func (b *BuilderS[T]) SetM(data map[string]any) (int, error)
- func (b *BuilderS[T]) ToChan(ptrChan *chan T) ([]T, error)
- func (b *BuilderS[T]) Trace() *BuilderS[T]
- func (b *BuilderS[T]) Where(query string, args ...any) *BuilderS[T]
- func (b *BuilderS[T]) WhereNamed(query string, args map[string]any) *BuilderS[T]
- type DashOpts
- type DatabaseEntity
- type Dialect
- type DocsError
- type DocsSuccess
- type Driver
- type ExecerQueryerContext
- func (conn ExecerQueryerContext) Begin() (driver.Tx, error)
- func (conn ExecerQueryerContext) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error)
- func (conn ExecerQueryerContext) Close() error
- func (conn ExecerQueryerContext) Exec(query string, args []driver.Value) (driver.Result, error)
- func (conn ExecerQueryerContext) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error)
- func (conn ExecerQueryerContext) Prepare(query string) (driver.Stmt, error)
- func (conn ExecerQueryerContext) PrepareContext(ctx context.Context, query string) (driver.Stmt, error)
- func (conn ExecerQueryerContext) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error)
- type ExecerQueryerContextWithSessionResetter
- func (conn ExecerQueryerContextWithSessionResetter) Begin() (driver.Tx, error)
- func (conn ExecerQueryerContextWithSessionResetter) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error)
- func (conn ExecerQueryerContextWithSessionResetter) Close() error
- func (conn ExecerQueryerContextWithSessionResetter) Exec(query string, args []driver.Value) (driver.Result, error)
- func (conn ExecerQueryerContextWithSessionResetter) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error)
- func (conn ExecerQueryerContextWithSessionResetter) Prepare(query string) (driver.Stmt, error)
- func (conn ExecerQueryerContextWithSessionResetter) PrepareContext(ctx context.Context, query string) (driver.Stmt, error)
- func (conn ExecerQueryerContextWithSessionResetter) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error)
- type HookData
- type HookFunc
- type Hooks
- type JsonOption
- type KV
- type LogEntry
- type Node
- type NodeManager
- func (nm *NodeManager) AddNode(node *Node) error
- func (nm *NodeManager) GetNode(addr string) *Node
- func (nm *NodeManager) GetNodes() []*Node
- func (nm *NodeManager) IsSecure(addr string) bool
- func (nm *NodeManager) RemoveNode(nodeAddr string)
- func (nm *NodeManager) Shutdown()
- func (nm *NodeManager) SyncData(targetNode *Node) error
- type OnErrorer
- type Selector
- func (sl *Selector[T]) Ctx(ct context.Context) *Selector[T]
- func (sl *Selector[T]) Database(dbName string) *Selector[T]
- func (sl *Selector[T]) Debug() *Selector[T]
- func (sl *Selector[T]) Named(statement string, args map[string]any, unsafe ...bool) error
- func (sl *Selector[T]) NoCache() *Selector[T]
- func (sl *Selector[T]) Query(statement string, args ...any) error
- func (sl *Selector[T]) Trace() *Selector[T]
- type SessionResetter
- func (conn SessionResetter) Begin() (driver.Tx, error)
- func (conn SessionResetter) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error)
- func (conn SessionResetter) Close() error
- func (conn SessionResetter) Prepare(query string) (driver.Stmt, error)
- func (conn SessionResetter) PrepareContext(ctx context.Context, query string) (driver.Stmt, error)
- type StatsFunc
- type Stmt
- func (stmt *Stmt) Close() error
- func (stmt *Stmt) Exec(args []driver.Value) (driver.Result, error)
- func (stmt *Stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error)
- func (stmt *Stmt) NumInput() int
- func (stmt *Stmt) Query(args []driver.Value) (driver.Rows, error)
- func (stmt *Stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error)
- type SystemMetrics
- type TableEntity
- type TablesInfos
- type TraceData
- type Tracer
- type TriggersQueue
- type User
Constants ¶
This section is empty.
Variables ¶
var ( ErrNoConnection = errors.New("no connection") ErrNoData = errors.New("no data") )
var ( BASIC_AUTH_USER = "notset" BASIC_AUTH_PASS = "testnotsetbutwaititshouldbeset" )
var ( // Debug when true show extra useful logs for queries executed for migrations and queries statements Debug = false // FlushCacheEvery execute korm.FlushCache() every 10 min by default, you should not worry about it, but useful that you can change it FlushCacheEvery = 10 * time.Minute // MaxOpenConns set max open connections for db pool MaxOpenConns = 50 // MaxIdleConns set max idle connections for db pool MaxIdleConns = 30 // MaxLifetime set max lifetime for a connection in the db pool MaxLifetime = 30 * time.Minute // MaxIdleTime set max idletime for a connection in the db pool MaxIdleTime = 30 * time.Minute )
var ( ErrTableNotFound = errors.New("unable to find tableName") ErrBigData = kmap.ErrLargeData )
var Admin = func(handler ksmux.Handler) ksmux.Handler { return func(c *ksmux.Context) { session, err := c.GetCookie("session") if err != nil || session == "" { c.DeleteCookie("session") c.Status(http.StatusTemporaryRedirect).Redirect(adminPathNameGroup + "/login") return } session, err = aes.Decrypt(session) if err != nil { c.Status(http.StatusTemporaryRedirect).Redirect(adminPathNameGroup + "/login") return } user, err := Model[User]().Where("uuid = ?", session).One() if err != nil { c.Status(http.StatusTemporaryRedirect).Redirect(adminPathNameGroup + "/login") return } if !user.IsAdmin { c.Status(403).Text("Middleware : Not allowed to access this page") return } c.SetKey("korm-user", user) handler(c) } }
var AllModelsGet = func(c *ksmux.Context) { model := c.Param("model") if model == "" { c.Json(map[string]any{ "error": "Error: No model given in params", }) return } dbMem, _ := GetMemoryDatabase(defaultDB) if dbMem == nil { lg.ErrorC("unable to find db in mem", "db", defaultDB) dbMem = &databases[0] } idString := "id" var t *TableEntity for i, tt := range dbMem.Tables { if tt.Name == model { idString = tt.Pk t = &dbMem.Tables[i] } } rows, err := Table(model).Database(defaultDB).OrderBy("-" + idString).Limit(paginationPer).Page(1).All() if err != nil { rows, err = Table(model).Database(defaultDB).All() if err != nil { if err != ErrNoData { c.Status(404).Error("Unable to find this model") return } } } dbCols, cols := GetAllColumnsTypes(model) mmfkeysModels := map[string][]map[string]any{} mmfkeys := map[string][]any{} if t != nil { for _, fkey := range t.Fkeys { spFrom := strings.Split(fkey.FromTableField, ".") if len(spFrom) == 2 { spTo := strings.Split(fkey.ToTableField, ".") if len(spTo) == 2 { q := "select * from " + spTo[0] + " order by " + spTo[1] mm := []map[string]any{} err := To(&mm).Query(q) if !lg.CheckError(err) { ress := []any{} for _, res := range mm { ress = append(ress, res[spTo[1]]) } if len(ress) > 0 { mmfkeys[spFrom[1]] = ress mmfkeysModels[spFrom[1]] = mm for _, v := range mmfkeysModels[spFrom[1]] { for i, vv := range v { if vvStr, ok := vv.(string); ok { if len(vvStr) > TruncatePer { v[i] = vvStr[:TruncatePer] + "..." } } } } } } else { lg.ErrorC("error:", "q", q, "spTo", spTo) } } } } } else { idString = cols[0] } if dbMem != nil { data := map[string]any{ "dbType": dbMem.Dialect, "table": model, "rows": rows, "dbcolumns": dbCols, "pk": idString, "fkeys": mmfkeys, "fkeysModels": mmfkeysModels, "columnsOrdered": cols, } if t != nil { data["columns"] = t.ModelTypes } else { data["columns"] = dbCols } c.Html("admin/admin_single_table.html", data) } else { lg.ErrorC("table not found", "table", model) c.Status(404).Error("Unable to find this model") } }
var AllModelsSearch = func(c *ksmux.Context) { model := c.Param("model") if model == "" { c.Json(map[string]any{ "error": "Error: No model given in params", }) return } body := c.BodyJson() blder := Table(model).Database(defaultDB) if query, ok := body["query"]; ok { if v, ok := query.(string); ok { if v != "" { blder.Where(v) } } else { c.Json(map[string]any{ "error": "Error: No query given in body", }) return } } oB := "" t, err := GetMemoryTable(model, defaultDB) if lg.CheckError(err) { c.Json(map[string]any{ "error": err, }) return } mmfkeysModels := map[string][]map[string]any{} mmfkeys := map[string][]any{} for _, fkey := range t.Fkeys { spFrom := strings.Split(fkey.FromTableField, ".") if len(spFrom) == 2 { spTo := strings.Split(fkey.ToTableField, ".") if len(spTo) == 2 { q := "select * from " + spTo[0] + " order by " + spTo[1] mm := []map[string]any{} err := To(&mm).Query(q) if !lg.CheckError(err) { ress := []any{} for _, res := range mm { ress = append(ress, res[spTo[1]]) } if len(ress) > 0 { mmfkeys[spFrom[1]] = ress mmfkeysModels[spFrom[1]] = mm for _, v := range mmfkeysModels[spFrom[1]] { for i, vv := range v { if vvStr, ok := vv.(string); ok { if len(vvStr) > TruncatePer { v[i] = vvStr[:TruncatePer] + "..." } } } } } } else { lg.ErrorC("error:", "q", q, "spTo", spTo) } } } } if oB != "" { blder.OrderBy(oB) } else { blder.OrderBy("-" + t.Pk) } pageNum := 1 if v, ok := body["page_num"]; ok { if pn, ok := v.(string); ok { if p, err := strconv.Atoi(pn); err == nil { pageNum = p } } } blder.Limit(paginationPer).Page(pageNum) data, err := blder.All() if err != nil { if err != ErrNoData { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } data = []map[string]any{} } // Get total count for pagination var total int64 var totalRows []int64 query := "SELECT COUNT(*) FROM " + model if v, ok := body["query"]; ok { if vStr, ok := v.(string); ok && vStr != "" { query += " WHERE " + vStr } } err = To(&totalRows).Query(query) if err == nil { total = totalRows[0] } c.Json(map[string]any{ "table": model, "rows": data, "cols": t.Columns, "types": t.ModelTypes, "fkeys": mmfkeys, "fkeysModels": mmfkeysModels, "total": total, }) }
var Auth = func(handler ksmux.Handler) ksmux.Handler { return func(c *ksmux.Context) { session, err := c.GetCookie("session") if err != nil || session == "" { c.DeleteCookie("session") handler(c) return } session, err = aes.Decrypt(session) if err != nil { handler(c) return } user, err := Model[User]().Where("uuid = ?", session).One() if err != nil { handler(c) return } c.SetKey("korm-user", user) handler(c) } }
var BasicAuth = func(handler ksmux.Handler) ksmux.Handler { return ksmux.BasicAuth(handler, BASIC_AUTH_USER, BASIC_AUTH_PASS) }
var BulkDeleteRowPost = func(c *ksmux.Context) { data := struct { Ids []uint Table string }{} if lg.CheckError(c.BodyStruct(&data)) { c.Error("BAD REQUEST") return } idString := "id" t, err := GetMemoryTable(data.Table, defaultDB) if err != nil { c.Status(404).Json(map[string]any{ "error": "table not found", }) return } if t.Pk != "" && t.Pk != "id" { idString = t.Pk } _, err = Table(data.Table).Database(defaultDB).Where(idString+" IN (?)", data.Ids).Delete() if lg.CheckError(err) { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } c.Json(map[string]any{ "success": "DELETED WITH SUCCESS", "ids": data.Ids, }) }
var ClearTraces = func(c *ksmux.Context) { ksmux.ClearTraces() c.Success("traces cleared") }
var CreateModelView = func(c *ksmux.Context) { data, files := c.ParseMultipartForm() model := data["table"][0] m := map[string]any{} for key, val := range data { switch key { case "table": continue case "uuid": if v := m[key]; v == "" { m[key] = GenerateUUID() } else { m[key] = val[0] } case "password": hash, _ := argon.Hash(val[0]) m[key] = hash case "email": if !IsValidEmail(val[0]) { c.Json(map[string]any{ "error": "email not valid", }) return } m[key] = val[0] case "pk": continue default: if key != "" && val[0] != "" && val[0] != "null" { m[key] = val[0] } } } inserted, err := Table(model).Database(defaultDB).InsertR(m) if err != nil { lg.ErrorC("CreateModelView error", "err", err) c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } idString := "id" t, _ := GetMemoryTable(data["table"][0], defaultDB) if t.Pk != "" && t.Pk != "id" { idString = t.Pk } pathUploaded, formName, err := handleFilesUpload(files, data["table"][0], fmt.Sprintf("%v", inserted[idString]), c, idString) if err != nil { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } if len(pathUploaded) > 0 { inserted[formName[0]] = pathUploaded[0] } c.Json(map[string]any{ "success": "Done !", "inserted": inserted, }) }
var DashView = func(c *ksmux.Context) { ddd := map[string]any{ "withRequestCounter": withRequestCounter, "stats": GetStats(), } if withRequestCounter { ddd["requests"] = GetTotalRequests() } c.Html("admin/admin_index.html", ddd) }
var DropTablePost = func(c *ksmux.Context) { data := c.BodyJson() if table, ok := data["table"]; ok && table != "" { if t, ok := data["table"].(string); ok { _, err := Table(t).Database(defaultDB).Drop() if lg.CheckError(err) { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } } else { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": "expecting 'table' to be string", }) } } else { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": "missing 'table' in body request", }) } c.Json(map[string]any{ "success": fmt.Sprintf("table %s Deleted !", data["table"]), }) }
var ExportCSVView = func(c *ksmux.Context) { table := c.Param("table") if table == "" { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": "no param table found", }) return } data, err := Table(table).Database(defaultDB).All() lg.CheckError(err) var buff bytes.Buffer writer := csv.NewWriter(&buff) cols := []string{} tab, _ := GetMemoryTable(table, defaultDB) if len(tab.Columns) > 0 { cols = tab.Columns } else if len(data) > 0 { d := data[0] for k := range d { cols = append(cols, k) } } err = writer.Write(cols) lg.CheckError(err) for _, sd := range data { values := []string{} for _, k := range cols { switch vv := sd[k].(type) { case string: values = append(values, vv) case bool: if vv { values = append(values, "true") } else { values = append(values, "false") } case int: values = append(values, strconv.Itoa(vv)) case int64: values = append(values, strconv.Itoa(int(vv))) case uint: values = append(values, strconv.Itoa(int(vv))) case time.Time: values = append(values, vv.String()) default: values = append(values, fmt.Sprintf("%v", vv)) } } err = writer.Write(values) lg.CheckError(err) } writer.Flush() c.Download(buff.Bytes(), table+".csv") }
var ExportView = func(c *ksmux.Context) { table := c.Param("table") if table == "" { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": "no param table found", }) return } data, err := Table(table).Database(defaultDB).All() lg.CheckError(err) data_bytes, err := json.Marshal(data) lg.CheckError(err) c.Download(data_bytes, table+".json") }
var GetLogsView = func(c *ksmux.Context) { parsed := make([]LogEntry, 0) if v := lg.GetLogs(); v != nil { for _, vv := range reverseSlice(v.Slice) { parsed = append(parsed, parseLogString(vv)) } } c.Json(parsed) }
var GetMetricsView = func(c *ksmux.Context) { metrics := GetSystemMetrics() c.Json(metrics) }
var GetTraces = func(c *ksmux.Context) { dbtraces := GetDBTraces() if len(dbtraces) > 0 { for _, t := range dbtraces { sp, _ := ksmux.StartSpan(context.Background(), t.Query) sp.SetTag("query", t.Query) sp.SetTag("args", fmt.Sprint(t.Args)) if t.Database != "" { sp.SetTag("database", t.Database) } sp.SetTag("duration", t.Duration.String()) sp.SetDuration(t.Duration) sp.SetError(t.Error) sp.End() } ClearDBTraces() } traces := ksmux.GetTraces() traceList := make([]map[string]interface{}, 0) for traceID, spans := range traces { spanList := make([]map[string]interface{}, 0) for _, span := range spans { errorMsg := "" if span.Error() != nil { errorMsg = span.Error().Error() } spanList = append(spanList, map[string]interface{}{ "id": span.SpanID(), "parentID": span.ParentID(), "name": span.Name(), "startTime": span.StartTime(), "endTime": span.EndTime(), "duration": span.Duration().String(), "tags": span.Tags(), "statusCode": span.StatusCode(), "error": errorMsg, }) } traceList = append(traceList, map[string]interface{}{ "traceID": traceID, "spans": spanList, }) } c.Json(traceList) }
var ImportView = func(c *ksmux.Context) { table := c.Request.FormValue("table") if table == "" { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": "no table !", }) return } t, err := GetMemoryTable(table, defaultDB) if lg.CheckError(err) { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } fname, dataBytes, err := c.UploadFile("thefile", "backup", "json", "csv") if lg.CheckError(err) { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } isCsv := strings.HasSuffix(fname, ".csv") modelsOld, _ := Table(table).Database(defaultDB).All() if len(modelsOld) > 0 { modelsOldBytes, err := json.Marshal(modelsOld) if !lg.CheckError(err) { _ = os.MkdirAll(mediaDir+"/backup/", 0770) dst, err := os.Create(mediaDir + "/backup/" + table + "-" + time.Now().Format("2006-01-02") + ".json") lg.CheckError(err) defer dst.Close() _, err = dst.Write(modelsOldBytes) lg.CheckError(err) } } list_map := []map[string]any{} if isCsv { reader := csv.NewReader(bytes.NewReader(dataBytes)) lines, err := reader.ReadAll() if lg.CheckError(err) { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } for _, values := range lines { m := map[string]any{} for i := range values { m[t.Columns[i]] = values[i] } list_map = append(list_map, m) } } else { err := json.Unmarshal(dataBytes, &list_map) if lg.CheckError(err) { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } } // create models in database var retErr []error for _, m := range list_map { _, err = Table(table).Database(defaultDB).Insert(m) if err != nil { retErr = append(retErr, err) } } if len(retErr) > 0 { c.Json(map[string]any{ "success": "some data could not be added, " + errors.Join(retErr...).Error(), }) return } c.Json(map[string]any{ "success": "Import Done , you can see uploaded backups at ./" + mediaDir + "/backup folder", }) }
var LoginPOSTView = func(c *ksmux.Context) { requestData := c.BodyJson() email := requestData["email"] passRequest := requestData["password"] data, err := Table("users").Database(defaultDB).Where("email = ?", email).One() if err != nil { c.Status(http.StatusUnauthorized).Json(map[string]any{ "error": err.Error(), }) return } if data["email"] == "" || data["email"] == nil { c.Status(http.StatusNotFound).Json(map[string]any{ "error": "User doesn not Exist", }) return } if data["is_admin"] == int64(0) || data["is_admin"] == 0 || data["is_admin"] == false { c.Status(http.StatusForbidden).Json(map[string]any{ "error": "Not Allowed to access this page", }) return } if passDB, ok := data["password"].(string); ok { if pp, ok := passRequest.(string); ok { if !argon.Match(passDB, pp) { c.Status(http.StatusForbidden).Json(map[string]any{ "error": "Wrong Password", }) return } else { if uuid, ok := data["uuid"].(string); ok { uuid, err = aes.Encrypt(uuid) lg.CheckError(err) c.SetCookie("session", uuid) c.Json(map[string]any{ "success": "U Are Logged In", }) return } } } } }
var LoginView = func(c *ksmux.Context) { c.Html("admin/admin_login.html", nil) }
var LogoutView = func(c *ksmux.Context) { c.DeleteCookie("session") c.Status(http.StatusTemporaryRedirect).Redirect("/") }
var LogsView = func(c *ksmux.Context) { d := map[string]any{ "metrics": GetSystemMetrics(), } parsed := make([]LogEntry, 0) if v := lg.GetLogs(); v != nil { for _, vv := range reverseSlice(v.Slice) { parsed = append(parsed, parseLogString(vv)) } } d["parsed"] = parsed c.Html("admin/admin_logs.html", d) }
var ManifestView = func(c *ksmux.Context) { if embededDashboard { f, err := staticAndTemplatesFS[0].ReadFile(staticDir + "/manifest.json") if err != nil { lg.ErrorC("cannot embed manifest.json", "err", err) return } c.ServeEmbededFile("application/json; charset=utf-8", f) } else { c.ServeFile("application/json; charset=utf-8", staticDir+"/manifest.json") } }
var (
MaxDbTraces = 50
)
var OfflineView = func(c *ksmux.Context) {
c.Text("<h1>YOUR ARE OFFLINE, check connection</h1>")
}
var RestartView = func(c *ksmux.Context) { if serverBus != nil { lg.CheckError(serverBus.App().Restart()) } }
var RobotsTxtView = func(c *ksmux.Context) {
c.ServeFile("text/plain; charset=utf-8", "."+staticUrl+"/robots.txt")
}
var ServiceWorkerView = func(c *ksmux.Context) { if embededDashboard { f, err := staticAndTemplatesFS[0].ReadFile(staticDir + "/sw.js") if err != nil { lg.ErrorC("cannot embed sw.js", "err", err) return } c.ServeEmbededFile("application/javascript; charset=utf-8", f) } else { c.ServeFile("application/javascript; charset=utf-8", staticDir+"/sw.js") } }
var TableGetAll = func(c *ksmux.Context) { model := c.Param("model") if model == "" { c.Json(map[string]any{ "error": "Error: No model given in params", }) return } dbMem, _ := GetMemoryDatabase(defaultDB) if dbMem == nil { lg.ErrorC("unable to find db in mem", "db", defaultDB) dbMem = &databases[0] } idString := "id" var t *TableEntity for i, tt := range dbMem.Tables { if tt.Name == model { idString = tt.Pk t = &dbMem.Tables[i] } } var body struct { Page int `json:"page"` } if err := c.BodyStruct(&body); lg.CheckError(err) { c.Error("something wrong happened") return } if body.Page == 0 { body.Page = 1 } rows, err := Table(model).Database(defaultDB).OrderBy("-" + idString).Limit(paginationPer).Page(body.Page).All() if err != nil { if err != ErrNoData { c.Status(404).Error("Unable to find this model") return } rows = []map[string]any{} } // Get total count for pagination var total int64 var totalRows []int64 err = To(&totalRows).Query("SELECT COUNT(*) FROM " + model) if err == nil { total = totalRows[0] } dbCols, cols := GetAllColumnsTypes(model) mmfkeysModels := map[string][]map[string]any{} mmfkeys := map[string][]any{} if t != nil { for _, fkey := range t.Fkeys { spFrom := strings.Split(fkey.FromTableField, ".") if len(spFrom) == 2 { spTo := strings.Split(fkey.ToTableField, ".") if len(spTo) == 2 { q := "select * from " + spTo[0] + " order by " + spTo[1] mm := []map[string]any{} err := To(&mm).Query(q) if !lg.CheckError(err) { ress := []any{} for _, res := range mm { ress = append(ress, res[spTo[1]]) } if len(ress) > 0 { mmfkeys[spFrom[1]] = ress mmfkeysModels[spFrom[1]] = mm for _, v := range mmfkeysModels[spFrom[1]] { for i, vv := range v { if vvStr, ok := vv.(string); ok { if len(vvStr) > TruncatePer { v[i] = vvStr[:TruncatePer] + "..." } } } } } } else { lg.ErrorC("error:", "q", q, "spTo", spTo) } } } } } else { idString = cols[0] } if dbMem != nil { ccc := cols if t != nil { ccc = t.Columns } data := map[string]any{ "dbType": dbMem.Dialect, "table": model, "rows": rows, "total": total, "dbcolumns": dbCols, "pk": idString, "fkeys": mmfkeys, "fkeysModels": mmfkeysModels, "columnsOrdered": ccc, } if t != nil { data["columns"] = t.ModelTypes } else { data["columns"] = dbCols } c.Json(map[string]any{ "success": data, }) } else { lg.ErrorC("table not found", "table", model) c.Status(404).Json(map[string]any{ "error": "table not found", }) } }
var TablesView = func(c *ksmux.Context) { allTables := GetAllTables(defaultDB) q := []string{} for _, t := range allTables { q = append(q, "SELECT '"+t+"' AS table_name,COUNT(*) AS count FROM "+t) } query := strings.Join(q, ` UNION ALL `) var results []struct { TableName string `db:"table_name"` Count int `db:"count"` } if err := To(&results).Query(query); lg.CheckError(err) { c.Error("something wrong happened") return } c.Html("admin/admin_tables.html", map[string]any{ "tables": allTables, "results": results, }) }
var TerminalComplete = func(c *ksmux.Context) { input := c.Request.URL.Query().Get("input") session := c.Request.URL.Query().Get("session") currentDir, _ := termsessions.Get(session) if currentDir == "" { currentDir, _ = os.Getwd() } parts := strings.Fields(input) if len(parts) == 0 { c.Json(map[string]any{"suggestions": []string{}}) return } lastWord := parts[len(parts)-1] targetDir := currentDir if strings.Contains(lastWord, "/") { pathParts := strings.Split(lastWord, "/") searchPattern := pathParts[len(pathParts)-1] searchDir := strings.Join(pathParts[:len(pathParts)-1], "/") if filepath.IsAbs(searchDir) { targetDir = searchDir } else { targetDir = filepath.Join(currentDir, searchDir) } files, err := os.ReadDir(targetDir) if err != nil { lg.Error("Error reading directory:", err) c.Json(map[string]any{"suggestions": []string{}}) return } suggestions := []string{} for _, file := range files { name := file.Name() if strings.HasPrefix(strings.ToLower(name), strings.ToLower(searchPattern)) { if file.IsDir() { name += "/" } suggestion := strings.Join([]string{searchDir, name}, "/") suggestions = append(suggestions, suggestion) } } c.Json(map[string]any{"suggestions": suggestions}) return } files, err := os.ReadDir(targetDir) if err != nil { lg.Error("Error reading directory:", err) c.Json(map[string]any{"suggestions": []string{}}) return } suggestions := []string{} for _, file := range files { name := file.Name() if strings.HasPrefix(strings.ToLower(name), strings.ToLower(lastWord)) { if file.IsDir() { name += "/" } suggestions = append(suggestions, name) } } c.Json(map[string]any{"suggestions": suggestions}) }
var TerminalExecute = func(c *ksmux.Context) { var req struct { Command string `json:"command"` Session string `json:"session"` } if err := c.BodyStruct(&req); err != nil { c.Json(map[string]any{"type": "error", "content": err.Error()}) return } currentDir, _ := termsessions.Get(req.Session) if currentDir == "" { currentDir, _ = os.Getwd() } output, newDir := executeCommand(req.Command, currentDir) termsessions.Set(req.Session, newDir) lg.Debug("Updated session directory:", newDir) c.Json(map[string]any{ "type": "output", "content": output, "directory": newDir, }) }
WebSocket endpoint for terminal
var TerminalGetView = func(c *ksmux.Context) { c.Html("admin/admin_terminal.html", nil) }
var TracingGetView = func(c *ksmux.Context) { c.Html("admin/admin_tracing.html", nil) }
var TruncatePer = 50
var UpdateRowPost = func(c *ksmux.Context) { data, files := c.ParseMultipartForm() id := data["row_id"][0] idString := "id" db, _ := GetMemoryDatabase(defaultDB) var t TableEntity for _, tab := range db.Tables { if tab.Name == data["table"][0] { t = tab } } if t.Pk != "" && t.Pk != "id" { idString = t.Pk } _, _, err := handleFilesUpload(files, data["table"][0], id, c, idString) if err != nil { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } modelDB, err := Table(data["table"][0]).Database(defaultDB).Where(idString+" = ?", id).One() if err != nil { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } ignored := []string{idString, "file", "image", "photo", "img", "fichier", "row_id", "table"} toUpdate := map[string]any{} quote := "`" if db.Dialect == POSTGRES || db.Dialect == COCKROACH { quote = "\"" } for key, val := range data { if !SliceContains(ignored, key) { if modelDB[key] == val[0] { continue } if key == "password" || key == "pass" { hash, err := argon.Hash(val[0]) if err != nil { c.Error("unable to hash pass") return } toUpdate[quote+key+quote] = hash } else { toUpdate[quote+key+quote] = val[0] } } } s := "" values := []any{} if len(toUpdate) > 0 { for col, v := range toUpdate { if s == "" { s += col + "= ?" } else { s += "," + col + "= ?" } values = append(values, v) } } if s != "" { _, err := Table(data["table"][0]).Database(defaultDB).Where(idString+" = ?", id).Set(s, values...) if err != nil { c.Status(http.StatusBadRequest).Json(map[string]any{ "error": err.Error(), }) return } } s = "" if len(files) > 0 { for f := range files { if s == "" { s += f } else { s += "," + f } } } if len(toUpdate) > 0 { for k := range toUpdate { if s == "" { s += k } else { s += "," + k } } } ret, err := Table(data["table"][0]).Database(defaultDB).Where(idString+" = ?", id).One() if err != nil { c.Status(500).Error("something wrong happened") return } c.Json(map[string]any{ "success": ret, }) }
Functions ¶
func AdaptNamedParams ¶ added in v1.8.0
func AdaptPlaceholdersToDialect ¶ added in v1.94.0
func AddChangesTrigger ¶ added in v1.95.8
AddChangesTrigger
func AddDashStats ¶ added in v1.95.2
func AddDashStats(fn ...StatsFunc)
func AddTrigger ¶
AddTrigger add trigger tablename_trig if col empty and tablename_trig_col if not
func AllowTerminalCommands ¶ added in v1.95.7
func AllowTerminalCommands(commands ...string)
AllowTerminalCommands adds commands to the allowed list for admin terminal
func DebugNodeManager ¶ added in v1.95.9
func DebugNodeManager()
func DifferenceBetweenSlices ¶ added in v1.4.1
func DifferenceBetweenSlices[T comparable](slice1 []T, slice2 []T) []T
func DisableCache ¶
func DisableCache()
DisableCache disable the cache system, if and only if you are having problem with it, also you can korm.FlushCache on command too
func DisableTracing ¶ added in v1.95.0
func DisableTracing()
DisableTracing turns off query tracing
func DisallowTerminalCommands ¶ added in v1.95.7
func DisallowTerminalCommands(commands ...string)
DisallowTerminalCommands removes commands from the allowed list
func DownloadFile ¶ added in v1.6.1
func DropTrigger ¶
DropTrigger drop trigger tablename_trig if column empty and tablename_trig_column if not
func ExecContext ¶ added in v1.8.0
ExecContext exec sql and return error if any
func ExecContextNamed ¶ added in v1.8.0
func ExecContextNamed(ctx context.Context, query string, args map[string]any, dbName ...string) error
ExecContextNamed exec named sql and return error if any
func FlushCache ¶
func FlushCache(tables ...string)
FlushCache send msg to the cache system to Flush all the cache, safe to use in concurrent mode, and safe to use in general, flushed every (korm.FlushCacheEvery)
func GenerateUUID ¶
func GenerateUUID() string
func GetAllColumnsTypes ¶
GetAllColumnsTypes get columns and types from the database
func GetAllTables ¶
GetAllTables get all tables for the optional dbName given, otherwise, if not args, it will return tables of the first connected database
func GetConnection ¶ added in v0.2.0
GetConnection get connection of dbName, if not specified , it return default, first database connected
func GetDatabaseSize ¶ added in v1.94.4
GetDatabaseSize returns the size of the database in GB or MB
func GetMemoryTableAndDB ¶ added in v1.4.1
func GetMemoryTableAndDB(tbName string, dbName ...string) (TableEntity, DatabaseEntity, error)
GetMemoryTable get a table from memory for specified or first connected db
func GetTotalRequests ¶ added in v1.94.4
func GetTotalRequests() uint64
GetTotalRequests returns the current total requests count
func InitShell ¶
func InitShell() bool
InitShell init the shell and return true if used to stop main
func IsValidEmail ¶ added in v1.5.4
func JSON_ARRAY ¶ added in v1.93.2
func JSON_EXTRACT ¶ added in v1.93.2
func JSON_EXTRACT(dataJson string, opt ...JsonOption) string
func JSON_OBJECT ¶ added in v1.93.2
func JSON_REMOVE ¶ added in v1.93.2
func JSON_REMOVE(dataJson string, opt ...JsonOption) string
func JSON_SET ¶ added in v1.93.2
func JSON_SET(dataJson string, opt ...JsonOption) string
func LogQueries ¶ added in v1.7.7
func LogQueries()
LogQueries enable logging sql statements with time tooked
func ManyToMany ¶ added in v1.1.0
ManyToMany create m2m_table1_table2 many 2 many table
func New ¶ added in v0.4.0
New the generic way to connect to all handled databases
Example: korm.New(korm.SQLITE, "db", sqlitedriver.Use()) korm.New(korm.MYSQL,"dbName", mysqldriver.Use(), "user:password@localhost:3333") korm.New(korm.POSTGRES,"dbName", pgdriver.Use(), "user:password@localhost:5432")
func PrintSystemMetrics ¶ added in v1.95.9
func PrintSystemMetrics()
PrintSystemMetrics prints the current system metrics
func RemoveFromSlice ¶ added in v1.4.1
func RemoveFromSlice[T comparable](slice *[]T, elemsToRemove ...T)
func ResetStruct ¶ added in v1.93.6
func ResetStruct(input interface{}) error
The input can be a struct, a pointer to a struct, or a pointer to a pointer to a struct.
func SetAdminPath ¶ added in v1.91.92
func SetAdminPath(path string)
SetAdminPath set admin path, default '/admin'
func SetCacheMaxMemory ¶ added in v1.4.3
func SetCacheMaxMemory(megaByte int)
SetCacheMaxMemory set max size of each cache cacheAllS AllM, minimum of 50 ...
func SetMaxDBTraces ¶ added in v1.95.0
func SetMaxDBTraces(max int)
SetMaxDBTraces sets the maximum number of traces to keep
func SliceContains ¶
func SliceContains[T comparable](elems []T, vs ...T) bool
func SliceToString ¶ added in v1.93.2
func SliceToString(slice interface{}) string
func StorageSize ¶ added in v1.4.5
func Transaction ¶ added in v1.3.9
Transaction create new database/sql transaction and return it, it can be rollback ...
func UnsafeNamedQuery ¶ added in v1.8.1
func WithBus ¶ added in v0.4.0
WithBus return ksbus.NewServer() that can be Run, RunTLS, RunAutoTLS
func WithDashboard ¶ added in v1.3.0
WithDashboard enable admin dashboard
func WithDocs ¶ added in v1.6.1
func WithDocs(generateJsonDocs bool, outJsonDocs string, handlerMiddlewares ...func(handler ksmux.Handler) ksmux.Handler) *kactor.BusServer
WithDocs enable swagger docs at DocsUrl default to '/docs/'
func WithEmbededDocs ¶ added in v1.6.4
func WithEmbededDocs(embeded embed.FS, embededDirPath string, handlerMiddlewares ...func(handler ksmux.Handler) ksmux.Handler) *kactor.BusServer
WithEmbededDocs same as WithDocs but embeded, enable swagger docs at DocsUrl default to '/docs/'
func WithMetrics ¶ added in v1.5.9
WithMetrics enable path /metrics (default), it take http.Handler like promhttp.Handler()
func WithPprof ¶ added in v1.5.9
WithPprof enable std library pprof at /debug/pprof, prefix default to 'debug'
func WithSchemaCheck ¶ added in v1.95.9
func WithSchemaCheck()
WithSchemaCheck enable struct changes check
Types ¶
type BuilderM ¶
type BuilderM struct {
// contains filtered or unexported fields
}
BuilderM is query builder map string any
func BuilderMap ¶
func BuilderMap() *BuilderM
func (*BuilderM) AddRelated ¶ added in v1.1.0
func (b *BuilderM) AddRelated(relatedTable string, whereRelatedTable string, whereRelatedArgs ...any) (int, error)
AddRelated used for many to many, and after korm.ManyToMany, to add a class to a student or a student to a class, class or student should exist in the database before adding them
func (*BuilderM) BulkInsert ¶ added in v1.2.6
BulkInsert insert many row at the same time in one query
func (*BuilderM) Delete ¶
Delete data from database, can be multiple, depending on the where, return affected rows(Not every database or database driver may support affected rows)
func (*BuilderM) DeleteRelated ¶ added in v1.1.0
func (b *BuilderM) DeleteRelated(relatedTable string, whereRelatedTable string, whereRelatedArgs ...any) (int, error)
DeleteRelated delete a relations many to many
func (*BuilderM) GetRelated ¶ added in v1.1.0
GetRelated used for many to many to get related classes to a student or related students to a class
func (*BuilderM) Insert ¶
Insert add row to a table using input map, and return PK of the inserted row
func (*BuilderM) InsertR ¶ added in v1.3.6
InsertR add row to a table using input map, and return the inserted row
func (*BuilderM) JoinRelated ¶ added in v1.1.0
JoinRelated same as get, but it join data
func (*BuilderM) OrderBy ¶
OrderBy can be used like: OrderBy("-id","-email") OrderBy("id","-email") OrderBy("+id","email")
func (*BuilderM) QueryMNamed ¶ added in v1.9.5
func (b *BuilderM) QueryMNamed(statement string, args map[string]any, unsafe ...bool) ([]map[string]any, error)
QueryMNamed query sql and return result as slice maps
Example:
QueryMNamed("select * from users where email = :email",map[string]any{ "email":"email@mail.com", })
func (*BuilderM) Set ¶
Set used to update, Set("email,is_admin","example@mail.com",true) or Set("email = ? AND is_admin = ?","example@mail.com",true)
type BuilderS ¶
type BuilderS[T any] struct { // contains filtered or unexported fields }
BuilderS is query builder for struct using generics
func BuilderStruct ¶ added in v1.0.2
BuilderStruct empty query to struct starter, default db first connected
func ModelTable ¶ added in v1.4.9
func (*BuilderS[T]) AddRelated ¶ added in v1.3.6
func (b *BuilderS[T]) AddRelated(relatedTable string, whereRelatedTable string, whereRelatedArgs ...any) (int, error)
AddRelated used for many to many, and after korm.ManyToMany, to add a class to a student or a student to a class, class or student should exist in the database before adding them
func (*BuilderS[T]) BulkInsert ¶ added in v1.3.6
BulkInsert insert many row at the same time in one query
func (*BuilderS[T]) Database ¶ added in v1.3.6
Database allow to choose database to execute query on
func (*BuilderS[T]) Debug ¶ added in v1.3.6
Debug print prepared statement and values for this operation
func (*BuilderS[T]) Delete ¶ added in v1.3.6
Delete data from database, can be multiple, depending on the where, return affected rows(Not every database or database driver may support affected rows)
func (*BuilderS[T]) DeleteRelated ¶ added in v1.3.6
func (b *BuilderS[T]) DeleteRelated(relatedTable string, whereRelatedTable string, whereRelatedArgs ...any) (int, error)
DeleteRelated delete a relations many to many
func (*BuilderS[T]) GetRelated ¶ added in v1.3.6
GetRelated used for many to many to get related classes to a student or related students to a class
func (*BuilderS[T]) InsertR ¶ added in v1.3.6
InsertR add row to a table using input struct, and return the inserted row
func (*BuilderS[T]) JoinRelated ¶ added in v1.3.6
JoinRelated same as get, but it join data
func (*BuilderS[T]) OrderBy ¶ added in v1.3.6
OrderBy can be used like: OrderBy("-id","-email") OrderBy("id","-email") OrderBy("+id","email")
func (*BuilderS[T]) Page ¶ added in v1.3.6
Page return paginated elements using Limit for specific page
func (*BuilderS[T]) QuerySNamed ¶ added in v1.9.5
func (b *BuilderS[T]) QuerySNamed(statement string, args map[string]any, unsafe ...bool) ([]T, error)
QueryNamedS query sql and return result as slice of structs T
Example:
QuerySNamed[models.User]("select * from users where email = :email",map[string]any{ "email":"email@mail.com", })
func (*BuilderS[T]) Set ¶ added in v1.3.6
Set used to update, Set("email,is_admin","example@mail.com",true) or Set("email = ? , is_admin = ?","example@mail.com",true)
type DashOpts ¶ added in v1.92.8
type DashOpts struct { ServerOpts *ksmux.Config EmbededStatic embed.FS EmbededTemplates embed.FS PaginatePer int // default 10 DocsUrl string // default docs MediaDir string // default media BaseDir string // default assets StaticDir string // default BaseDir/static TemplatesDir string // default BaseDir/templates Path string // default /admin RepoUser string // default kamalshkeir RepoName string // default korm-dash WithTracing bool // add tracing handling page in dash and enable tracing WithTerminal bool // add terminal session handling page in dash WithNodeManager bool // add node manager handling page in dash WithRequestCounter bool // add request counter dashboard,default false }
type DatabaseEntity ¶
type DatabaseEntity struct { Tables []TableEntity Name string Dialect string Conn *sql.DB }
DatabaseEntity hold memory db state
func GetDefaultDbMem ¶ added in v1.95.9
func GetDefaultDbMem() *DatabaseEntity
func GetMemoryDatabase ¶
func GetMemoryDatabase(dbName string) (*DatabaseEntity, error)
GetMemoryDatabase return the first connected database korm.DefaultDatabase if dbName "" or "default" else the matched db
func GetMemoryDatabases ¶
func GetMemoryDatabases() []DatabaseEntity
GetMemoryDatabases get all databases from memory
type Dialect ¶ added in v1.1.0
type Dialect = string
Dialect db dialects are SQLITE, POSTGRES, MYSQL, MARIA, COCKROACH
type DocsError ¶ added in v1.6.9
type DocsError struct {
Error string `json:"error" example:"error message"`
}
type DocsSuccess ¶ added in v1.6.9
type DocsSuccess struct {
Success string `json:"success" example:"success message"`
}
type ExecerQueryerContext ¶ added in v1.7.7
type ExecerQueryerContext struct {
// contains filtered or unexported fields
}
ExecerQueryerContext implements database/sql.driver.ExecerContext and database/sql.driver.QueryerContext
func (ExecerQueryerContext) ExecContext ¶ added in v1.8.0
func (ExecerQueryerContext) PrepareContext ¶ added in v1.8.0
func (ExecerQueryerContext) QueryContext ¶ added in v1.8.0
type ExecerQueryerContextWithSessionResetter ¶ added in v1.7.7
type ExecerQueryerContextWithSessionResetter struct { *SessionResetter // contains filtered or unexported fields }
ExecerQueryerContext implements database/sql.driver.ExecerContext and database/sql.driver.QueryerContext
func (ExecerQueryerContextWithSessionResetter) Close ¶ added in v1.8.0
func (conn ExecerQueryerContextWithSessionResetter) Close() error
func (ExecerQueryerContextWithSessionResetter) ExecContext ¶ added in v1.8.0
func (ExecerQueryerContextWithSessionResetter) PrepareContext ¶ added in v1.8.0
func (ExecerQueryerContextWithSessionResetter) QueryContext ¶ added in v1.8.0
type Hooks ¶ added in v1.7.7
type Hooks interface { Before(ctx context.Context, query string, args ...interface{}) (context.Context, error) After(ctx context.Context, query string, args ...interface{}) (context.Context, error) }
Hooks instances may be passed to Wrap() to define an instrumented driver
type JsonOption ¶ added in v1.93.2
type Node ¶ added in v1.95.9
type Node struct { ID string `json:"id"` Address string `json:"address"` Active bool `json:"active"` Secure bool `json:"secure"` }
Node represents a KORM node in the cluster
type NodeManager ¶ added in v1.95.9
type NodeManager struct {
// contains filtered or unexported fields
}
NodeManager handles node registration and data synchronization
func GetNodeManager ¶ added in v1.95.9
func GetNodeManager() *NodeManager
func WithNodeManager ¶ added in v1.95.9
func WithNodeManager() *NodeManager
func (*NodeManager) AddNode ¶ added in v1.95.9
func (nm *NodeManager) AddNode(node *Node) error
func (*NodeManager) GetNode ¶ added in v1.95.9
func (nm *NodeManager) GetNode(addr string) *Node
func (*NodeManager) GetNodes ¶ added in v1.95.9
func (nm *NodeManager) GetNodes() []*Node
func (*NodeManager) IsSecure ¶ added in v1.95.9
func (nm *NodeManager) IsSecure(addr string) bool
func (*NodeManager) RemoveNode ¶ added in v1.95.9
func (nm *NodeManager) RemoveNode(nodeAddr string)
func (*NodeManager) Shutdown ¶ added in v1.95.9
func (nm *NodeManager) Shutdown()
func (*NodeManager) SyncData ¶ added in v1.95.9
func (nm *NodeManager) SyncData(targetNode *Node) error
SyncData send all tables to targetNode sync_data
type OnErrorer ¶ added in v1.7.7
type OnErrorer interface {
OnError(ctx context.Context, err error, query string, args ...interface{}) error
}
OnErrorer instances will be called if any error happens
type Selector ¶ added in v1.9.6
type Selector[T any] struct { // contains filtered or unexported fields }
type SessionResetter ¶ added in v1.7.7
type SessionResetter struct {
// contains filtered or unexported fields
}
type Stmt ¶ added in v1.7.7
Stmt implements a database/sql/driver.Stmt
func (*Stmt) ExecContext ¶ added in v1.7.7
func (*Stmt) QueryContext ¶ added in v1.7.7
type SystemMetrics ¶ added in v1.95.9
type SystemMetrics struct { // Memory metrics HeapMemoryMB float64 // Currently allocated heap memory in MB SystemMemoryMB float64 // Total memory obtained from system in MB StackMemoryMB float64 // Memory used by goroutine stacks HeapObjects uint64 // Number of allocated heap objects HeapReleasedMB float64 // Memory released to the OS in MB // Garbage Collection metrics NumGC uint32 // Number of completed GC cycles LastGCTimeSec float64 // Time since last garbage collection in seconds GCCPUPercent float64 // Fraction of CPU time used by GC (0-100) // Runtime metrics NumGoroutines int // Current number of goroutines NumCPU int // Number of logical CPUs GoVersion string // Go version used to build the program }
SystemMetrics holds memory and runtime statistics for the application
func GetSystemMetrics ¶ added in v1.95.9
func GetSystemMetrics() SystemMetrics
GetSystemMetrics returns memory and runtime statistics for the application
type TableEntity ¶
type TableEntity struct { Types map[string]string ModelTypes map[string]string Tags map[string][]string Columns []string Fkeys []kormFkey Pk string Name string }
DatabaseEntity hold table state
func GetMemoryTable ¶
func GetMemoryTable(tbName string, dbName ...string) (TableEntity, error)
GetMemoryTable get a table from memory for specified or first connected db
func GetTablesInfosFromDB ¶ added in v1.95.9
func GetTablesInfosFromDB(tables ...string) []TableEntity
type TablesInfos ¶ added in v1.95.9
type TraceData ¶ added in v1.95.0
type TraceData struct { Query string // The SQL query Args []any // Query arguments Database string // Database name StartTime time.Time // When the query started Duration time.Duration // How long it took Error error // Any error that occurred }
TraceData represents a single trace entry
func GetDBTraces ¶ added in v1.95.0
func GetDBTraces() []TraceData
GetDBTraces returns all stored traces
func TraceQuery ¶ added in v1.95.0
func TraceQuery(ctx context.Context, db *DatabaseEntity, query string, args ...any) (TraceData, error)
TraceQuery wraps a query execution with tracing
type Tracer ¶ added in v1.95.0
type Tracer struct {
// contains filtered or unexported fields
}
Tracer handles query tracing functionality
type TriggersQueue ¶ added in v1.95.8
type User ¶ added in v1.3.0
type User struct { Id int `json:"id,omitempty" korm:"pk"` Uuid string `json:"uuid,omitempty" korm:"size:40;iunique"` Username string `json:"username,omitempty" korm:"size:40;iunique"` Email string `json:"email,omitempty" korm:"size:50;iunique"` Password string `json:"password,omitempty" korm:"size:150;default:''"` IsAdmin bool `json:"is_admin,omitempty" korm:"default:false"` Image string `json:"image,omitempty" korm:"size:100;default:''"` CreatedAt time.Time `json:"created_at,omitempty" korm:"now"` }