| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 | 
							- package sdb
 
- import (
 
- 	"context"
 
- 	"database/sql"
 
- 	"errors"
 
- 	"runtime"
 
- 	"time"
 
- )
 
- const (
 
- 	driverName = "sqlite3"
 
- )
 
- type DB struct {
 
- 	FileName string
 
- 	w        *sql.DB
 
- 	r        *sql.DB
 
- }
 
- type TableInfo struct {
 
- 	Name        string
 
- 	ColumnsInfo []ColumnInfo
 
- }
 
- func (t *TableInfo) Column(col string) *ColumnInfo {
 
- 	for i, c := range t.ColumnsInfo {
 
- 		if c.Name == col {
 
- 			return &t.ColumnsInfo[i]
 
- 		}
 
- 	}
 
- 	return nil
 
- }
 
- type ColumnInfo struct {
 
- 	Name         string
 
- 	Type         string
 
- 	NotNull      bool
 
- 	DefaultValue any
 
- }
 
- func (c *ColumnInfo) TypePool() any {
 
- 	return handleColumnType(c.Type)
 
- }
 
- func Open(name string) (*DB, error) {
 
- 	w, err := sql.Open(driverName, name)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	w.SetMaxOpenConns(1) // 写线程设置为 1 个
 
- 	r, err := sql.Open(driverName, name)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	r.SetMaxOpenConns(runtime.NumCPU())
 
- 	sdb := &DB{
 
- 		FileName: name,
 
- 		w:        w,
 
- 		r:        r,
 
- 	}
 
- 	return sdb, nil
 
- }
 
- func (s *DB) Close() error {
 
- 	es := make([]error, 0, 2)
 
- 	if err := s.w.Close(); err != nil {
 
- 		es = append(es, err)
 
- 	}
 
- 	if err := s.r.Close(); err != nil {
 
- 		es = append(es, err)
 
- 	}
 
- 	return errors.Join(es...)
 
- }
 
- func (s *DB) createCtx() (context.Context, context.CancelFunc) {
 
- 	return context.WithTimeout(context.Background(), 5*time.Second)
 
- }
 
- func (s *DB) Query(query string, args ...any) ([]M, error) {
 
- 	ctx, cancel := s.createCtx()
 
- 	rows, err := Query(ctx, s.r, query, args...)
 
- 	cancel()
 
- 	return rows, err
 
- }
 
- func (s *DB) QueryRow(query string, args ...any) (M, error) {
 
- 	rows, err := s.Query(query, args...)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	if len(rows) == 0 {
 
- 		return M{}, nil
 
- 	}
 
- 	return rows[0], nil
 
- }
 
- func (s *DB) Count(fieldNum int, query string, args ...any) ([]int64, error) {
 
- 	ctx, cancel := s.createCtx()
 
- 	defer cancel()
 
- 	row := s.r.QueryRowContext(ctx, query, args...)
 
- 	if err := row.Err(); err != nil {
 
- 		return nil, err
 
- 	}
 
- 	scan := func() (arg []any) {
 
- 		for i := 0; i < fieldNum; i++ {
 
- 			arg = append(arg, new(int64))
 
- 		}
 
- 		return
 
- 	}()
 
- 	if err := row.Scan(scan...); err != nil {
 
- 		return nil, err
 
- 	}
 
- 	count := make([]int64, fieldNum)
 
- 	for i, num := range scan {
 
- 		count[i] = *num.(*int64)
 
- 	}
 
- 	return count, nil
 
- }
 
- func (s *DB) Exec(query string, args ...any) error {
 
- 	ctx, cancel := s.createCtx()
 
- 	err := Exec(ctx, s.w, query, args...)
 
- 	cancel()
 
- 	return err
 
- }
 
- func (s *DB) Execs(query string, args ...[]any) error {
 
- 	ctx, cancel := s.createCtx()
 
- 	err := Execs(ctx, s.w, query, args...)
 
- 	cancel()
 
- 	return err
 
- }
 
- func (s *DB) Columns(table string) ([]ColumnInfo, error) {
 
- 	ctx, cancel := s.createCtx()
 
- 	cols, err := Columns(ctx, s.r, table)
 
- 	cancel()
 
- 	return cols, err
 
- }
 
- func (s *DB) Tables() ([]TableInfo, error) {
 
- 	tblName, err := TableNames(s.r)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	ctx, cancel := s.createCtx()
 
- 	defer cancel()
 
- 	infos := make([]TableInfo, len(tblName))
 
- 	for i, name := range tblName {
 
- 		info, err := Columns(ctx, s.r, name)
 
- 		if err != nil {
 
- 			return infos, err
 
- 		}
 
- 		infos[i] = TableInfo{
 
- 			Name:        name,
 
- 			ColumnsInfo: info,
 
- 		}
 
- 	}
 
- 	return infos, nil
 
- }
 
- func (s *DB) HasTable(tblName string) bool {
 
- 	tblList, _ := s.Tables()
 
- 	for _, tbl := range tblList {
 
- 		if tbl.Name == tblName {
 
- 			return true
 
- 		}
 
- 	}
 
- 	return false
 
- }
 
 
  |