orm

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2025 License: MIT Imports: 7 Imported by: 4

README

This is for simple ORM that can be used from all packages

Simple ORM that is independent of the database

Documentation

Index

Constants

View Source
const (
	DEFAULT_PAGINATION_LIMIT     = 50
	DEFAULT_MAX_MULTIPLE_INSERTS = 100 // Maximum number of rows to insert in a single SQL statement
)

Variables

View Source
var (
	// Some global vars are needed so we can change this on the fly later on.
	// For example: we read the MAX_MULTIPLE_INSERTS from db.settings then
	// it will be changed on the fly when function that need this variable got called!
	ErrSQLNoRows         medaerror.MedaError = medaerror.MedaError{Message: "select returns no rows"}
	ErrSQLMoreThanOneRow medaerror.MedaError = medaerror.MedaError{Message: "select returns more than 1 rows"}
	MAX_MULTIPLE_INSERTS int                 = DEFAULT_MAX_MULTIPLE_INSERTS
)

Functions

func ConvertSQLCommands

func ConvertSQLCommands(lines []string) []string

Convert the .sql file into each individual sql commands Input is []string which are the content of the .sql file Output is []string of each sql commands.

func InterfaceToSQLString

func InterfaceToSQLString(interfaceVal interface{}) string

func PrintDebug

func PrintDebug(msg string)

===== THis is for debugging purposes

func SecondToMs

func SecondToMs(s float64) float64

func SecondToMsString

func SecondToMsString(s float64) string

func ToInsertSQLRawFromSlice

func ToInsertSQLRawFromSlice(records []DBRecord) []string

ToInsertSQLRawFromSlice converts a slice of DBRecord to a slice of raw SQL statements by converting to DBRecords first

func TotalTimeElapsedInSecond

func TotalTimeElapsedInSecond(reses []BasicSQLResult) float64

Get all sum timing

Types

type BasicSQLResult

type BasicSQLResult struct {
	Error        error
	Timing       float64
	RowsAffected int
	LastInsertID int
}

mostly used for rawSQL execution, this is the return, empty if it's not applicable This is not for query where we return usually DBRecord or DBRecords / []DBRecord

type Condition

type Condition struct {
	Field    string      `json:"field,omitempty"        db:"field"`
	Operator string      `json:"operator,omitempty"     db:"operator"`
	Value    interface{} `json:"value,omitempty"        db:"value"`
	Logic    string      `json:"logic,omitempty"        db:"logic"`    // "AND" or "OR"
	Nested   []Condition `json:"nested,omitempty"       db:"nested"`   // For nested conditions
	OrderBy  []string    `json:"order_by,omitempty"     db:"order_by"` // Fields to order by
	GroupBy  []string    `json:"group_by,omitempty"     db:"group_by"` // Fields to group by
	Limit    int         `json:"limit,omitempty"        db:"limit"`    // Limit for pagination
	Offset   int         `json:"offset,omitempty"       db:"offset"`   // Offset for pagination
}

Condition struct for query filtering with JSON and DB tags This struct is used to define conditions for filtering data in queries. It supports various operations like AND, OR, and nested conditions. Sample usage:

// Simple condition
condition := Condition{
  Field:    "age",
  Operator: ">",
  Value:    18,
}
// Output: WHERE age > 18

// Nested condition with AND logic
condition := Condition{
  Logic: "AND",
  Nested: []Condition{
    Condition{Field: "age", Operator: ">", Value: 18},
    Condition{Field: "status", Operator: "=", Value: "active"},
  },
}
// Output: WHERE (age > 18 AND status = 'active')

// Nested condition with OR logic
condition := Condition{
  Logic: "OR",
  Nested: []Condition{
    Condition{Field: "status", Operator: "=", Value: "pending"},
    Condition{Field: "status", Operator: "=", Value: "review"},
  },
}
// Output: WHERE (status = 'pending' OR status = 'review')

// Complex condition with nested AND and OR
condition := Condition{
  Logic: "OR",
  Nested: []Condition{
    Condition{
      Logic: "AND",
      Nested: []Condition{
        Condition{Field: "age", Operator: ">", Value: 18},
        Condition{Field: "country", Operator: "=", Value: "USA"},
      },
    },
    Condition{
      Logic: "AND",
      Nested: []Condition{
        Condition{Field: "status", Operator: "=", Value: "active"},
        Condition{Field: "role", Operator: "=", Value: "admin"},
      },
    },
  },
}
// Output: WHERE ((age > 18 AND country = 'USA') OR (status = 'active' AND role = 'admin'))

func (*Condition) And

func (c *Condition) And(conditions ...Condition) *Condition

And creates a new Condition with AND logic for the given conditions. This method allows chaining multiple conditions together with AND logic. Usage:

condition.And(
  Condition{Field: "age", Operator: ">", Value: 18},
  Condition{Field: "status", Operator: "=", Value: "active"}
)

Returns: A new Condition with nested conditions joined by AND

func (*Condition) Or

func (c *Condition) Or(conditions ...Condition) *Condition

Or creates a new Condition with OR logic for the given conditions. This method allows chaining multiple conditions together with OR logic. Usage:

condition.Or(
  Condition{Field: "status", Operator: "=", Value: "pending"},
  Condition{Field: "status", Operator: "=", Value: "review"}
)

Returns: A new Condition with nested conditions joined by OR

func (*Condition) ToSelectString

func (c *Condition) ToSelectString(tableName string) (string, []interface{})

ToSelectString generates a complete SELECT SQL query string with WHERE, GROUP BY, ORDER BY, and LIMIT/OFFSET clauses based on the Condition struct. Usage:

query, values := condition.ToSelectString("users")

Returns:

  • string: Complete SELECT query (e.g., "SELECT * FROM users WHERE age > ? ORDER BY name LIMIT 10")
  • []interface{}: Slice of values for the parameterized query

func (*Condition) ToWhereString

func (c *Condition) ToWhereString() (string, []interface{})

ToWhereString converts a Condition struct into a WHERE clause string and parameter values. It handles nested conditions recursively and supports both AND/OR logic. Usage:

whereClause, values := condition.ToWhereString()

Returns:

  • string: SQL WHERE clause with parameterized queries (e.g., "field1 = ? AND (field2 > ?)")
  • []interface{}: Slice of values corresponding to the parameters

type DBRecord

type DBRecord struct {
	TableName string
	Data      map[string]interface{}
}

func TableStructToDBRecord

func TableStructToDBRecord(obj TableStruct) (DBRecord, error)

func (*DBRecord) FromStruct

func (d *DBRecord) FromStruct(obj TableStruct) error

FromStruct converts a TableStruct object to a DBRecord. It maps the struct fields to the DBRecord's Data map and sets the table name. Usage:

var record DBRecord
record.FromStruct(userStruct)

Returns: error if conversion fails

func (*DBRecord) ToInsertSQLParameterized

func (d *DBRecord) ToInsertSQLParameterized() (string, []interface{})

Convert DBRecord to SQL Insert string and values but with placeholder (parameterized) ToInsertSQLParameterized converts a single DBRecord to a parameterized INSERT SQL statement. Usage:

sql, values := record.ToInsertSQLParameterized()

Returns:

  • string: Parameterized INSERT query (e.g., "INSERT INTO table (col1, col2) VALUES (?, ?)")
  • []interface{}: Slice of values for the parameters

func (*DBRecord) ToInsertSQLRaw

func (d *DBRecord) ToInsertSQLRaw() (string, []interface{})

Convert DBRecord to SQL Insert string and values ToInsertSQLRaw converts a single DBRecord to a raw INSERT SQL statement with values. Usage:

sql, values := record.ToInsertSQLRaw()

Returns:

  • string: Complete INSERT query with values (e.g., "INSERT INTO table (col1, col2) VALUES ('value1', 2)")
  • []interface{}: Slice of original values (for reference)

type DBRecords

type DBRecords []DBRecord

func DBRecordsFromSlice

func DBRecordsFromSlice(records []DBRecord) DBRecords

DBRecordsFromSlice converts a slice of DBRecord to DBRecords type and uses the DBRecords methods

func (*DBRecords) Append

func (d *DBRecords) Append(rec DBRecord)

Append adds a new DBRecord to the DBRecords slice. Usage:

records.Append(newRecord)

func (DBRecords) ToInsertSQLParameterized

func (records DBRecords) ToInsertSQLParameterized() []ParametereizedSQL

NOTE: For not same tables that are in DBRecords then use the DBRecord.ToInsertSQLParameterized() function for each record in DBRecords.

BULK inserts, one is parameterized and non-parameterized (just plain raw SQL) This is always for same table only, not for different tables!

ToInsertSQLParameterized converts multiple DBRecords to a slice of parameterized INSERT statements. It automatically batches inserts according to MAX_MULTIPLE_INSERTS limit. Usage:

statements := records.ToInsertSQLParameterized()

Returns: Slice of ParametereizedSQL containing batched INSERT statements and their values

func (DBRecords) ToInsertSQLRaw

func (records DBRecords) ToInsertSQLRaw() []string

ToInsertSQLRaw converts multiple DBRecords to a slice of raw INSERT SQL statements. It automatically batches inserts according to MAX_MULTIPLE_INSERTS limit. Usage:

statements := records.ToInsertSQLRaw()

Returns: Slice of strings containing complete INSERT statements with values

type DataStruct

type DataStruct struct {
	TypeDef string // string | int | bool | etc
	Value   interface{}
	Empty   bool // this to replace the nil value if data is not set
}

TODO: replace the DBRecord.Data to be map[string]DataStruct . this will be more robust and flexible

type Database

type Database interface {
	GetSchema(bool, bool) []SchemaStruct
	Status() (NodeStatusStruct, error)

	SelectOne(string) (DBRecord, error)   // This is almost unusable, very rare case
	SelectMany(string) (DBRecords, error) // This is almost unusable, very rare case (this is like select ALL rows from the table)
	SelectOneWithCondition(string, *Condition) (DBRecord, error)
	SelectManyWithCondition(string, *Condition) ([]DBRecord, error)

	SelectOneSQL(string) (DBRecords, error)                              // select using one sql statement
	SelectManySQL([]string) ([]DBRecords, error)                         // select using many sql statements
	SelectOnlyOneSQL(string) (DBRecord, error)                           // select only returning 1 row, and also check if actually more than 1 return errors
	SelectOneSQLParameterized(ParametereizedSQL) (DBRecords, error)      // select using one parameterized sql statement
	SelectManySQLParameterized([]ParametereizedSQL) ([]DBRecords, error) // select using many parameterized sql statements
	SelectOnlyOneSQLParameterized(ParametereizedSQL) (DBRecord, error)   // select only returning 1 row, and also check if actually more than 1 return errors

	ExecOneSQL(string) BasicSQLResult
	ExecOneSQLParameterized(ParametereizedSQL) BasicSQLResult
	ExecManySQL([]string) ([]BasicSQLResult, error)
	ExecManySQLParameterized([]ParametereizedSQL) ([]BasicSQLResult, error)

	InsertOneDBRecord(DBRecord, bool) BasicSQLResult
	InsertManyDBRecords([]DBRecord, bool) ([]BasicSQLResult, error)
	InsertManyDBRecordsSameTable([]DBRecord, bool) ([]BasicSQLResult, error)

	// TableStruct is less practical
	InsertOneTableStruct(TableStruct, bool) BasicSQLResult
	InsertManyTableStructs([]TableStruct, bool) ([]BasicSQLResult, error)

	// Status and Health check
	IsConnected() bool
	Leader() (string, error)  // this was originally for RQLite, if not then just return empty string or "not implemented"
	Peers() ([]string, error) // this was originally for RQLite, if not then just return empty string or "not implemented"

}

type NodeStatusStruct

type NodeStatusStruct struct {
	StatusStruct
	Peers map[int]StatusStruct // all peers including the leader
}

NodeStatusStruct is a struct that contains the status of a node, including its peers (if has peers) It is mostly derived from the SettingsTable but is used for response. Mode is : r , w, or rw (for read only, write only and read and write) Example of how to use it:

var nodeStatus NodeStatusStruct
nodeStatus.StatusStruct = StatusStruct{...}
nodeStatus.Peers = map[int]StatusStruct{...}

Output:

{
  "url": "http://localhost:4001",
  "version": "3.5.0",
  "start_time": "2022-01-01T00:00:00Z",
  "uptime": "24h0m0s",
  "dir_size": 1024,
  "db_size": 2048,
  "node_id": "node1",
  "is_leader": true,
  "leader": "node1",
  "last_backup": "2022-01-01T00:00:00Z",
  "mode": "standalone",
  "nodes": 1,
  "node_number": 1,
  "peers": {
    2: {
      "url": "http://localhost:4002",
      "version": "3.5.0",
      "start_time": "2022-01-01T00:00:00Z",
      "uptime": "24h0m0s",
      "dir_size": 1024,
      "db_size": 2048,
      "node_id": "node2",
      "is_leader": false,
      "leader": "node1",
      "last_backup": "2022-01-01T00:00:00Z",
      "mode": "r",
      "nodes": 2,
      "node_number": 2
    }
  }
}

func (*NodeStatusStruct) PrintPretty

func (s *NodeStatusStruct) PrintPretty()

This function is used to print the status of the node in a pretty format, including its peers. Example of how to use it: s.PrintPretty() Output: A formatted string representation of the node's status and its peers. This is mainly for debugging and logging

type ParametereizedSQL

type ParametereizedSQL struct {
	Query  string        `json:"query"`
	Values []interface{} `json:"values,omitempty"`
}

func SQLAndValuesToParameterized

func SQLAndValuesToParameterized(q string, p []interface{}) ParametereizedSQL

func ToInsertSQLParameterizedFromSlice

func ToInsertSQLParameterizedFromSlice(records []DBRecord) []ParametereizedSQL

ToInsertSQLParameterizedFromSlice converts a slice of DBRecord to a slice of ParametereizedSQL by converting to DBRecords first

type SchemaStruct

type SchemaStruct struct {
	ObjectType string `json:"type"           db:"type"`
	ObjectName string `json:"name"           db:"name"`
	TableName  string `json:"tbl_name"       db:"tbl_name"`
	RootPage   int    `json:"rootpage"       db:"rootpage"`
	SQLCommand string `json:"sql"            db:"sql"`
	Hidden     bool   `json:"hidden"         db:"hidden"`
}

Struct to get the schema from sqlite_master table in SQLite

func (SchemaStruct) PrintDebug

func (s SchemaStruct) PrintDebug(sql bool)

PrintDebug prints debug information about a database schema object. If sql parameter is true, it includes the SQL command in the output. Usage:

schema.PrintDebug(true)

Output Example:

Object [table] : users[users_table] - CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)

type StatusStruct

type StatusStruct struct {
	URL        string        `json:"url,omitempty"          db:"url"`         // URL (host + port)
	Version    string        `json:"version,omitempty"      db:"version"`     // version of the DMBS
	DBMS       string        `json:"dbms,omitempty"         db:"dbms"`        // version of the DMBS
	DBMSDriver string        `json:"dbms_driver,omitempty"  db:"dbms_driver"` // version of the DMBS
	StartTime  time.Time     `json:"start_time,omitempty"   db:"start_time"`
	Uptime     time.Duration `json:"uptime,omitempty"       db:"uptime"`
	DirSize    int64         `json:"dir_size,omitempty"     db:"dir_size"` // if applicable
	DBSize     int64         `json:"db_size,omitempty"      db:"db_size"`  // if applicable
	NodeID     string        `json:"node_id,omitempty"      db:"node_id"`  // DBMS node ID, was rqlite node_id from status
	IsLeader   bool          `json:"is_leader,omitempty"    db:"is_leader"`
	Leader     string        `json:"leader,omitempty"       db:"leader"`      // complete address (including protocol, ie: https://...)
	LastBackup time.Time     `json:"last_backup,omitempty"  db:"last_backup"` // if applicable
	Mode       string        `json:"mode,omitempty"         db:"mode"`        // options are r, w, or rw
	Nodes      int           `json:"nodes,omitempty"        db:"nodes"`       // total number of nodes in the cluster
	NodeNumber int           `json:"node_number,omitempty"  db:"node_number"` // this node number, actually this is not applicable in rqlite, because NodeID is string
	MaxPool    int           `json:"max_pool,omitempty"     db:"max_pool"`    // if applicable

}

Struct to use as per-node status, information mostly from SettingsTable, but this is used for response

func (*StatusStruct) PrintPretty

func (s *StatusStruct) PrintPretty(indent, title string)

This function is used to print the status of a node in a pretty format, mainly for debugging and logging purposes. Example usage: nodeStatus.PrintPretty("", "Node Status") Output: A formatted string representation of the node's status, including URL, version, start time, uptime, directory size, database size, node ID, leadership status, leader ID, last backup time, mode, number of nodes, and node number. This is mainly for debugging and logging

type TableStruct

type TableStruct interface {
	TableName() string
}

Make sure other table struct that you use implement this method

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL