github.com/goplus/yap@v0.8.1/ydb/classfile.go (about)

     1  /*
     2   * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package ydb
    18  
    19  import (
    20  	"context"
    21  	"database/sql"
    22  	"flag"
    23  	"log"
    24  	"reflect"
    25  	"strings"
    26  )
    27  
    28  const (
    29  	GopPackage = "github.com/goplus/yap/test"
    30  )
    31  
    32  var (
    33  	debugExec bool
    34  )
    35  
    36  // -----------------------------------------------------------------------------
    37  
    38  type Sql struct {
    39  	driver *Engine
    40  	wrap   func(string, error) error
    41  
    42  	tables  map[string]*Table
    43  	classes map[string]*Class
    44  	db      *sql.DB
    45  
    46  	autodrop bool
    47  }
    48  
    49  func (p *Sql) initSql() {
    50  	p.tables = make(map[string]*Table)
    51  	p.classes = make(map[string]*Class)
    52  }
    53  
    54  // Engine initializes database by specified engine name.
    55  func (p *Sql) Engine__0(name string) {
    56  	driver, ok := engines[name]
    57  	if !ok {
    58  		log.Panicf("engine `%s` not found: please call ydb.Register first\n", name)
    59  	}
    60  	defaultDataSource := driver.TestSource
    61  	dataSource, ok := defaultDataSource.(string)
    62  	if !ok {
    63  		dataSource = defaultDataSource.(func() string)()
    64  	}
    65  	const (
    66  		autodropParam = "autodrop"
    67  	)
    68  	if strings.HasSuffix(dataSource, autodropParam) {
    69  		dataSource = dataSource[:len(dataSource)-len(autodropParam)-1]
    70  		p.autodrop = true
    71  	}
    72  	db, err := sql.Open(name, dataSource)
    73  	if err != nil {
    74  		log.Panicln("sql.Open:", err)
    75  	}
    76  	p.db = db
    77  	p.driver = driver
    78  	p.wrap = driver.WrapErr
    79  }
    80  
    81  // Engine returns engine name of the database.
    82  func (p *Sql) Engine__1() string {
    83  	return p.driver.Name
    84  }
    85  
    86  func (p *Sql) defineTable(nameVer string, zeroSchema any) {
    87  	var name, ver string
    88  	pos := strings.IndexByte(nameVer, ' ') // user v0.1.0
    89  	if pos < 0 {
    90  		ver = nameVer
    91  	} else {
    92  		name, ver = nameVer[:pos], strings.TrimLeft(nameVer[pos+1:], " \t")
    93  	}
    94  	schema := reflect.TypeOf(zeroSchema).Elem()
    95  	if name == "" {
    96  		name = dbName(schema.Name())
    97  	}
    98  	if _, ok := p.tables[name]; ok {
    99  		log.Panicf("table `%s` exists\n", name)
   100  	}
   101  	tbl := newTable(name, ver, schema)
   102  	p.tables[name] = tbl
   103  	tbl.create(context.TODO(), p)
   104  }
   105  
   106  func dbName(fldName string) string {
   107  	c := fldName[0]
   108  	if c >= 'A' && c <= 'Z' {
   109  		c += ('a' - 'A')
   110  	}
   111  	return string(c) + fldName[1:]
   112  }
   113  
   114  // Table creates a new table by specified Schema.
   115  func Gopt_Sql_Gopx_Table[Schema any](sql interface{ defineTable(string, any) }, nameVer string) {
   116  	sql.defineTable(nameVer, (*Schema)(nil))
   117  }
   118  
   119  // -----------------------------------------------------------------------------
   120  
   121  type Engine struct {
   122  	Name       string
   123  	TestSource any // can be a `string` or a `func() string` object.
   124  	WrapErr    func(prompt string, err error) error
   125  }
   126  
   127  var (
   128  	engines = make(map[string]*Engine) // engineName => engine
   129  )
   130  
   131  // Register registers an engine.
   132  func Register(e *Engine) {
   133  	engines[e.Name] = e
   134  }
   135  
   136  // -----------------------------------------------------------------------------
   137  
   138  type AppGen struct {
   139  }
   140  
   141  func (p *AppGen) initApp() {
   142  }
   143  
   144  func Gopt_AppGen_Main(app interface{ initApp() }, workers ...interface{ initClass(self any) }) {
   145  	flag.BoolVar(&debugExec, "v", false, "verbose infromation")
   146  	flag.Parse()
   147  	app.initApp()
   148  	if me, ok := app.(interface{ MainEntry() }); ok {
   149  		me.MainEntry()
   150  	}
   151  	for _, worker := range workers {
   152  		worker.initClass(worker)
   153  		worker.(interface{ Main() }).Main()
   154  	}
   155  }
   156  
   157  // -----------------------------------------------------------------------------