Code Monkey home page Code Monkey logo

qbs's People

Contributors

adam-frisby avatar bryant1410 avatar coocood avatar iansmith avatar jchenry avatar jmcvetta avatar liudch avatar nuvivo314 avatar robfig avatar tejainece avatar vadimi avatar yiziz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

qbs's Issues

CreateTableIfNotExists is only creating Id column

When I executed CreateTableIfNotExists on a struct, it only creates Id column.

I tried to debug it and found that in function structPtrToModel in models.go file, all the other fields are getting omitted in this following code,

fieldValue := structValue.FieldByName(structField.Name)
if !fieldValue.CanInterface() {
    continue
}

Panic in qbs.Count wrt row.Scan on qbs.go:610

There is a panic in qbs.Count when the rows returned to count don't exist (because the table doesn't exist yet, the connection hasn't come up yet, etc).

2015/02/10 01:46:58 setting up DB: postgres://postgres:seekret@localhost/candidate?sslmode=disable
qbs:2015/02/10 01:46:58 pq: the database system is starting up
qbs:2015/02/10 01:46:58 pq: the database system is starting up
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x6ba924]

goroutine 26 [running]:
runtime.panic(0x863220, 0xb4ddd3)
        /opt/go/src/pkg/runtime/panic.c:279 +0xf5
database/sql.(*Row).Scan(0x0, 0x7f715abf8d90, 0x1, 0x1, 0x0, 0x0)
        /opt/go/src/pkg/database/sql/sql.go:1636 +0x44
github.com/coocood/qbs.(*Qbs).Count(0xc208060880, 0x891fc0, 0xc208029b20, 0x0)
        /go/src/github.com/coocood/qbs/qbs.go:610 +0x293

If you look at qbs.go:610, you'll see that it calls the following:

if q.criteria.condition != nil {
        conditionSql, args := q.criteria.condition.Merge()
        query += " WHERE " + conditionSql
        row = q.QueryRow(query, args...)
} else {
        row = q.QueryRow(query)
}
var count int64
err := row.Scan(&count)

And QueryRow can return a nil row, thus calling the row.Scan with a nil row value:

func (q *Qbs) QueryRow(query string, args ...interface{}) *sql.Row {
        q.log(query, args...)
        query = q.Dialect.substituteMarkers(query)
        stmt, err := q.prepare(query)
        if err != nil {
                q.updateTxError(err)
                return nil
        }
        return stmt.QueryRow(args...)
}

In this case q.prepare is failing, as postgres is still coming up. Thus return nil is called, and not checked in the callers of QueryRow. I see this as a bug in:

  • ContainsValue on line 578
  • Count on line 610

Whereas doQueryRow returns the errors all the way out. I'm pushing a pull request that fixes this up a bit in a moment.

Current status

Tell me please, what is current status of project?
Latest commit on Jan, is development stopped?

Pronunciation

What is the preferred English pronunciation of qbs? I like "cubes" - it sounds a lot nicer than "queue bee ess". :)

FindAll get empty

package main

import (
	"fmt"
	"github.com/coocood/qbs"
	_ "github.com/mattn/go-sqlite3"
	"time"
)

type Book struct {
	Id int64
	Title     string
	Author    string
	Published time.Time
}


func main() {

	qbs.Register("sqlite3", "book.db", "qbs_test", qbs.NewSqlite3())

	q, err := qbs.GetQbs()
 
	migration, err := qbs.GetMigration()

	defer migration.Close()
	err = migration.CreateTableIfNotExists(new(Book))
	fmt.Println(err)

 
	var book = &Book{
		Title:     "new book",
		Author:    "qbs",
		Published: time.Now(),
	}

	out, err := q.Save(book)
 
	fmt.Println(out,err)
 
	var books []*Book
	err = q.Limit(10).Offset(10).FindAll(&books)
	fmt.Println(err)
	for k, v := range books {

		fmt.Println(k, v)
	}
	
/*
sqlite> select * from book;
4|new book|qbs|2021-10-14 07:27:48.3926642+08:00
*/
	

}

Missing Assrt

D:\GOPATH\src\github.com\coocood\qbs>go install
testutil_db.go:6:2: cannot find package "github.com/coocood/assrt" in any of:
c:\go\src\pkg\github.com\coocood\assrt (from $GOROOT)
D:\GOPATH\src\github.com\coocood\assrt (from $GOPATH)

Forgot to commit something?

Title case field naming

Hi,
I would like to test QBS performance on the TechEmpower Benchmarks. However, the test uses a database schema that uses TitleCase naming convention instead of snake_case -- is it possible to change the convention, or QBS only supports snake case?
Thanks!
Rob

reflect.Set: value of type []uint8 is not assignable to type time.Time

type User struct {
    Id             int64
    Loginname      string    `qbs:"size:50,notnull,unique"`
    Name, Password string    `qbs:"size:50,index"`
    Registered     bool      `qbs:"default:false,notnull,index"`
    Created        time.Time `qbs:"index"`
    Updated        time.Time `qbs:"index"`
}

func FindUserById(q *qbs.Qbs, id int64) (*User, error) {
    user := new(User)
    user.Id = id
    err := q.Find(user)
    return user, err
}

//////////////////////////////////////////////////////////////////////////////

    q, err := qbs.GetQbs()
    if err != nil {
        fmt.Println(err)
        this.Controller.Ctx.ResponseWriter.WriteHeader(500)
        return
    }
    defer q.Close()
    u, err := db.FindUserById(q, 1)
    fmt.Fprintf(this.Controller.Ctx.ResponseWriter, u.Loginname)

//////////////////////////////////////////////////////////////////////////////////
error:
reflect.Set: value of type []uint8 is not assignable to type time.Time
github.com/coocood/qbs.base.setModelValue(0x1f0bb7e0, 0x1f010828, 0x5fc800, 0x1f0ebfb8, 0x146, ...)
D:/My Design/golang/src/github.com/coocood/qbs/base.go:56 +0x415

数据库配置文件错误,导致 CreateTableIfNotExists 创建表时,报字段重复错误

qbs.Register("mysql", "root:password@/database1?charset=utf8&parseTime=true&loc=Local", "database2", qbs.NewMysql())

如上述配置文件中,database1不同于database2虽然可以正常创建表,但会导致在CreateTableIfNotExists检查数据库中字段数目是否相等时,用到的TABLE_SCHEMA 不同,qbs会重新添加字段,实际上字段已经存在,所以报如下错误

Duplicate column name 'xx'

看是否有必要检查此配置文件错误,并给出友好提示啊?

Save uses value zero for insert with pk

When we try to insert a struct with Id as pk and Name as string, the result query with arguments is:

INSERT INTO `cars` (`id`, `name`) VALUES (?, ?) []interface {}{0, "test"}

when it should be

INSERT INTO `cars` (`name`) VALUES (?) []interface {}{"test"}

or

INSERT INTO `cars` (`id`, `name`) VALUES (?, ?) []interface {}{NULL, "test"}

执行多次qbs.Exec后报1461错误

请教,在执行多次qbs.Exec(sql)后,会报这个错误
1461: Can' t create more than max_prepared_stmt_count statements (current value: 16382)
数据库显示:
| Com_stmt_close | 456 |
| Com_stmt_execute | 132936 |
| Com_stmt_fetch | 0 |
| Com_stmt_prepare | 91187 |
请问,要在哪进行com_stmt_close关闭

struct field time.Time turn into text after migration

package main

import (
	"fmt"
	"github.com/coocood/qbs"
	_ "github.com/mattn/go-sqlite3"
	"log"

	"time"
)

type Blog struct {
	Id int64
 
	Title     string    `db:"title"`
	Author    string    `db:"author"`
	Published time.Time `db:"published"`
}

func checkErr(err error, msg string) {
	if err != nil {
		log.Fatalln(msg, err)
	}
}

func main() {

	qbs.Register("sqlite3", "blog.db", "qbs_test", qbs.NewSqlite3())

	q, err := qbs.GetQbs()
	fmt.Print(q, err)
	migration, err := qbs.GetMigration()
 
	defer migration.Close()
	err = migration.CreateTableIfNotExists(new(Blog))
	fmt.Println(err)
}

generate table schema

CREATE TABLE `blog` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `title` text, `author` text, `published` text )

struct 中包含非基本数据类型的 field时提示 panic: invalid sql type 错误

例如有如下需求:

type TranStatus uint16

const (
    Isolated  = TranStatus(0x10) 
    Canceled  = TranStatus(0x20) 
    Pending   = TranStatus(0x40) 
    Completed = TranStatus(0x80)
)

type Transaction struct {   
    Session      string    `qbs:"size:32,pk"` 
    Sys          string    `qbs:"size:20"`   
    SysTrans     string    `qbs:"size:32"` 
    BeginTime    time.Time 
    CancelTime   time.Time
    CompleteTime time.Time 
    IsolateTime  time.Time 
    Status       TranStatus   
}

其中Transaction中的Status非基本数据类型,在创建数据表时抛出panic: invalid sql type错误

建议提供更友好的错误提示,或者支持此类操作,golang本身的json库能很好的处理该问题:http://play.golang.org/p/pQ9qkXS_HV

qbs.go:51: db.SetMaxIdleConns undefined

when I "go get github.com/coocood/qbs" there is a problem,How can I fix it?

michael2008s$ go get github.com/coocood/qbs

github.com/coocood/qbs

src/github.com/coocood/qbs/qbs.go:51: db.SetMaxIdleConns undefined (type *sql.DB has no field or method SetMaxIdleConns)
src/github.com/coocood/qbs/qbs.go:100: db.SetMaxIdleConns undefined (type *sql.DB has no field or method SetMaxIdleConns)

q.find查不出数据求救

表结构
CREATE TABLE md_grab_product (
id int(11) NOT NULL AUTO_INCREMENT,
product_name varchar(100) NOT NULL COMMENT '产品名字',
product_desc varchar(255) NOT NULL COMMENT '产品描述',
market_price int(11) NOT NULL COMMENT '市场价格 单位是分',
max_price int(11) NOT NULL COMMENT '最大价格 单位是分',
min_price int(11) NOT NULL DEFAULT '1' COMMENT '最小价格 单位是分',
product_count int(11) NOT NULL DEFAULT '1' COMMENT '产品总数',
surplus_count int(11) NOT NULL DEFAULT '1' COMMENT '产品剩余的总数',
alert_price int(11) NOT NULL DEFAULT '0' COMMENT '警示价',
grab_start_time datetime NOT NULL COMMENT '抢购开始时间',
grab_end_time datetime NOT NULL COMMENT '抢购结束时间',
createtime datetime NOT NULL COMMENT '创建时间',
upatetime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
KEY start (grab_start_time),
KEY end (grab_end_time)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='抢购产品表'

struct:
type Md_grab_product struct {
Id int64
Product_name string qbs:"size:100"
Product_desc string qbs:"size:255"
Market_price int64
Max_price int64
Min_price int64
Product_count int64
Surplus_count int64
Alert_price int64
Grab_start_time time.Time
Grab_end_time time.Time
Createtime time.Time
}

方法:
func FindById(q _qbs.Qbs, id int64) (_Md_grab_product, error) {
q.Log = true
grabProduct := new(Md_grab_product)
grabProduct.Id = id
err := q.Find(grabProduct)
return grabProduct, err
}

sql log:
qbs:2013/11/26 17:59:55 SELECT id, product_name, product_desc, market_price, max_price, min_price, product_count, surplus_count, alert_price, grab_start_time, grab_end_time, createtime FROM md_grab_product WHERE md_grab_product.id = ? LIMIT ?
qbs:2013/11/26 17:59:55 2 1

死活查不出数据求救

Please support sqlite3 type "datetime"

Sqlite3 has an own data type for timestamps: datetime.
Qbs does not support "datetime" with sqlite. So it's hard to use an existing database.

When I use "text" for my time.Time types, it's working well. But this is not acceptable, because it is not possible to use the sqlite datetime features.

difficulty in WhereEqual

HI, I created a table with this structure:

type Groups struct {
    Id            int64 `qbs:"pk"`
    FacultyId     int64 `qbs:"fk:Faculty"`
    Faculty       *Faculties
    FullName      string `qbs:"size:100"`
    ShortName     string `qbs:"size:20"`
    NumOfStudents int
    Year          int
}

And when I use the function WhereEqual() in this context:

group := new(Groups)
err := q.WhereEqual("ShortName", "string").Find(group)

I have an error "Unknown column 'ShortName'"
In real table this column named as "short_name", but when I write:

err := q.WhereEqual("short_name", "string").Find(group)

I have an error "Column 'short_name' in where clause is ambiguous".

what to do in this situation? rename table columns? or is there another method?

Bulk insert enhancements

I noticed that lib/pq started to support COPY FROM STDIN. Does it make sense to rewrite BulkInsert method to use this technique for postgres (maybe by making it a part of dialect)? It is so much faster to import large amounts of data using COPY FROM STDIN.

Find(interface{}) returning wrong result

Using postgres dialect on PostgreSQL 9.1.9

for struct:

type Foo  struct {
  Id int64
  Text string
}

inserting

Foo { Id: 1, Text:"bar"}

using Save then doing a Find with

Foo { Id: 0, Text: "baz"}

will return

Foo { Id: 1, Text:"bar"}

pretty certain it should return an error of no rows found since it doesn't match any.

Recursive struct by FK

Hello,

I'm from test this:

type Test struct {
  Id qbs.Id
  FatherId int64 `sql:"fk:Father"`
  Father *Test
}

If i'm make, 3 elems,

t0.FatherId = 0
t1.FatherId = t0.Id
t2.FatherId = t1.Id

And want to Find t2.

t := &Test{Id: 3}
qbs.Find(t)

t.Father -> Ok
t.Father.Father -> nil

My question is:
You know this "effect" or "not-effect", if yes, you wand to make recursively in future? Or just 1 parent ?

Personally, the both is ok for my app.

Regards.

(Sorry for my English.)

Faster Insert row

Currently I only read the docs and i read this:

If Id is set to a positive integer, Save would query the count of the row to find
out if the row already exists, if not then execute INSERT statement.
otherwise execute UPDATE.

This is not the best solution, since you need 3 queries to check if a row exists.
It would be way easier to just update the row. Check if the query was successfull or greater than zero and if not just insert the statement.

struct中存在未导出的字段时,CreateTableIfNotExists 提示反射错误。

我定义的struct如下:

type Card struct {
    Id     int64     `qbs:"index"` 
    Worth  float64   
    KeyPre int64     `qbs:"unique"
    keySub int64     
    Hash   string    `qbs:"size:40,index"` 
    User   int64     
    Time   time.Time 
}

其中的 keySub 不需要导出,在调用 CreateTableIfNotExists ,提示如下错误:

panic: reflect.Value.Interface: cannot return value obtained from unexported field or method

goroutine 1 [running]:
reflect.valueInterface(0x501560, 0x126a9ed8, 0x67, 0x126ac301, 0x1, ...)
    D:/workspace/golang/sdk/1.1/src/pkg/reflect/value.go:983 +0x99
reflect.Value.Interface(0x501560, 0x126a9ed8, 0x67, 0x0, 0x0, ...)
    D:/workspace/golang/sdk/1.1/src/pkg/reflect/value.go:972 +0x41
github.com/coocood/qbs.structPtrToModel(0x52cc60, 0x126a9ec0, 0x1d0001, 0x0, 0x0, ...)
    D:/workspace/golang/3rdparty/src/github.com/coocood/qbs/model.go:194 +0x468
github.com/coocood/qbs.(*Migration).CreateTableIfNotExists(0x126bce20, 0x52cc60, 0x126a9ec0, 0x1, 0x1, ...)
    D:/workspace/golang/3rdparty/src/github.com/coocood/qbs/migration.go:19 +0x4b

应该是 model.go 在反射字段时,未排查unexported field

more than one embeddings

Can I create struct like this:
User -> Account -> Subscription with FK
and then get third from first,
like User.Account.Subscription.Name?

If I try get fields values from second, all good
User.Account.SomeField,
but when I try get access to User.Account.Subscription, it return nil.

Cannot load MYSQL longtext fields into Go strings

I have a table in a MySQL database describable by the following qbs struct

type LongTextTable struct {
    Id int64
    Parent_id int64 `qbs:"fk:Parent"`
    Parent *ParentTable
    Key string `qbs:"size:255"`
    String_value string `qbs:"size:4294967295"` // This field is longtext, null in the table
}

I cannot seem to load the String_value field from the db, though I can load the other fields just fine using FindAll(). Are longtext fields supported by qbs or am I perhaps doing something wrong?

FindAll(scanRows) Panic

Hello,
First one, thank you for your work.

I found a bug in FindAll(qbs.scanRows).
Here is the error:

panic: reflect: call of reflect.Value.FieldByName on zero Value

goroutine 1 [running]:
reflect.flag.mustBe(0x0, 0x19, 0x100000001, 0x0)
        /opt/golang/src/pkg/reflect/value.go:241 +0xa2
reflect.Value.FieldByName(0x0, 0x0, 0x0, 0xf840074fc0, 0x2, ...)
        /opt/golang/src/pkg/reflect/value.go:688 +0x40
github.com/coocood/qbs.(*Qbs).scanRows(0xf840032780, 0x47fa38, 0xf840078440, 0x160, 0xf840077a20, ...)
        ./exp_qbs/src/github.com/coocood/qbs/qbs.go:218 +0x524
github.com/coocood/qbs.(*Qbs).doQueryRows(0xf840032780, 0x47e8b8, 0xf84006e180, 0xf840079000, 0xf8000001ca, ...)
        ./exp_qbs/src/github.com/coocood/qbs/qbs.go:192 +0x3ba
github.com/coocood/qbs.(*Qbs).FindAll(0xf840032780, 0x47e8b8, 0xf84006e180, 0xf84006e180, 0xf840060fc0, ...)
        ./exp_qbs/src/github.com/coocood/qbs/qbs.go:149 +0x1fd
main.main()
        ./exp_qbs/qbs_exp.go:80 +0xdcf

goroutine 2 [syscall]:
created by runtime.main
        /opt/golang/src/pkg/runtime/proc.c:221
exit status 2

Short snippet code:

 tmpFindAll := make([]*Event, 0)
 o.Limit(2).FindAll(&tmpFindAll)

My structure is nested, i thinks is linked.

So I tinker a fix:

diff --git a/qbs.go b/qbs.go
index d989102..2861dc3 100644

--- a/qbs.go
+++ b/qbs.go
@@ -215,9 +215,6 @@ func (q *Qbs) scanRows(rowValue reflect.Value, rows *sql.Rows) (err error) {
                paths := strings.Split(key, "___")
                if len(paths) == 2 {
                        subStruct := rowValue.Elem().FieldByName(snakeToUpperCamel(paths[0]))
+                       if subStruct.IsNil() {
+                               subStruct.Set(reflect.New(subStruct.Type().Elem()))
+                       }
                        subField := subStruct.Elem().FieldByName(snakeToUpperCamel(paths[1]))
                        if subField.IsValid() {
                                err = q.Dialect.SetModelValue(value, subField)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.