diff --git a/ql/_dumps/structs.sql b/ql/_dumps/structs.sql index 372e5eed1cfef37802820f88279bd9497a4e9fa1..96ca94f519fc18d7c4a6620f68396d8415f9e654 100644 --- a/ql/_dumps/structs.sql +++ b/ql/_dumps/structs.sql @@ -54,4 +54,14 @@ CREATE TABLE stats_test ( value int64 ); +DROP TABLE IF EXISTS composite_keys; + +-- Composite keys are currently not supported in QL. +CREATE TABLE composite_keys ( +-- code string, +-- user_id string, + some_val string, +-- primary key (code, user_id) +); + COMMIT; diff --git a/ql/collection.go b/ql/collection.go index 5ad91f3ad397578b12de40061452f2e45d4323fb..07b889f04502eb1df3af1a7e04d238d1b4ea580e 100644 --- a/ql/collection.go +++ b/ql/collection.go @@ -79,6 +79,14 @@ func whereValues(term interface{}) (where sqlgen.Where, args []interface{}) { for _, kk := range k { where = append(where, kk) } + case db.Constrainer: + k, v := conditionValues(t.Constraint()) + args = append(args, v...) + for _, kk := range k { + where = append(where, kk) + } + default: + panic(fmt.Sprintf(db.ErrUnknownConditionType.Error(), reflect.TypeOf(t))) } return where, args @@ -245,6 +253,13 @@ func (t *table) Append(item interface{}) (interface{}, error) { var id int64 id, _ = res.LastInsertId() + // Does the item satisfy the db.ID interface? + if setter, ok := item.(db.IDSetter); ok { + if err := setter.SetID([]interface{}{id}...); err != nil { + return nil, err + } + } + return id, nil } diff --git a/ql/database_test.go b/ql/database_test.go index 64a9b89eac6b5cb68f1466980394bf4debcf139a..6befcf76ae1365490365fef94f5428a7cfa38a36 100644 --- a/ql/database_test.go +++ b/ql/database_test.go @@ -34,6 +34,7 @@ import ( "menteslibres.net/gosexy/to" //"reflect" + "errors" "math/rand" "strings" "testing" @@ -77,6 +78,26 @@ type testValuesStruct struct { Time time.Duration `field:"_time"` } +type ItemWithKey struct { + ID int64 `db:",omitempty"` + SomeVal string `db:"some_val"` +} + +func (item ItemWithKey) Constraint() db.Cond { + cond := db.Cond{ + "id()": item.ID, + } + return cond +} + +func (item *ItemWithKey) SetID(keys ...interface{}) error { + if len(keys) == 1 { + item.ID = keys[0].(int64) + return nil + } + return errors.New(`Expecting exactly two keys.`) +} + var testValues testValuesStruct func init() { @@ -1120,6 +1141,66 @@ func TestTransactionsAndRollback(t *testing.T) { } +// QL: Does not support composite keys, so we're testing db.Constrainer and +// db.IDSetter interface. +func TestCompositeKeys(t *testing.T) { + var err error + var id interface{} + var sess db.Database + var compositeKeys db.Collection + + if sess, err = db.Open(Adapter, settings); err != nil { + t.Fatal(err) + } + + defer sess.Close() + + if compositeKeys, err = sess.Collection("composite_keys"); err != nil { + t.Fatal(err) + } + + //n := rand.Intn(100000) + + item := ItemWithKey{ + // "ABCDEF", + // strconv.Itoa(n), + 0, + "Some value", + } + + if id, err = compositeKeys.Append(&item); err != nil { + t.Fatal(err) + } + + // ids := id.([]interface{}) + + // if ids[0].(string) != item.Code { + // t.Fatal(`Keys must match.`) + // } + // + // if ids[1].(string) != item.UserID { + // t.Fatal(`Keys must match.`) + // } + + // Using constraint interface. + res := compositeKeys.Find(ItemWithKey{ID: id.(int64)}) + + var item2 ItemWithKey + + if item2.SomeVal == item.SomeVal { + t.Fatal(`Values must be different before query.`) + } + + if err := res.One(&item2); err != nil { + t.Fatal(err) + } + + if item2.SomeVal != item.SomeVal { + t.Fatal(`Values must be equal after query.`) + } + +} + /* // Attempts to add many different datatypes to a single row in a collection, // then it tries to get the stored datatypes and check if the stored and the