diff --git a/db/create.go b/db/create.go index 94462b56..dfdb2fd0 100644 --- a/db/create.go +++ b/db/create.go @@ -66,6 +66,16 @@ func (e *executor) executeCreate(ctx context.Context, stm *sql.CreateStatement) key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, ID: nil} i.processBatch(ctx, key, what) + // Result of subquery + case []interface{}: + key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB} + i.processOther(ctx, key, what) + + // Result of subquery with LIMIT 1 + case map[string]interface{}: + key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB} + i.processOther(ctx, key, []interface{}{what}) + } } diff --git a/db/delete.go b/db/delete.go index 1341d0b0..441e320d 100644 --- a/db/delete.go +++ b/db/delete.go @@ -65,6 +65,16 @@ func (e *executor) executeDelete(ctx context.Context, stm *sql.DeleteStatement) key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, ID: nil} i.processBatch(ctx, key, what) + // Result of subquery + case []interface{}: + key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB} + i.processOther(ctx, key, what) + + // Result of subquery with LIMIT 1 + case map[string]interface{}: + key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB} + i.processOther(ctx, key, []interface{}{what}) + } } diff --git a/db/iterator.go b/db/iterator.go index 1aa135f7..9da6ce5d 100644 --- a/db/iterator.go +++ b/db/iterator.go @@ -693,13 +693,13 @@ func (i *iterator) processModel(ctx context.Context, key *keys.Thing, qry *sql.M } -func (i *iterator) processQuery(ctx context.Context, key *keys.Thing, val []interface{}) { +func (i *iterator) processOther(ctx context.Context, key *keys.Thing, val []interface{}) { i.processPerms(ctx, key.NS, key.DB, key.TB) - for _, val := range val { + for _, v := range val { - switch val := val.(type) { + switch v := v.(type) { case *sql.Thing: @@ -710,7 +710,52 @@ func (i *iterator) processQuery(ctx context.Context, key *keys.Thing, val []inte if i.checkState(ctx) { key := key.Copy() - key.TB, key.ID = val.TB, val.ID + key.TB, key.ID = v.TB, v.ID + i.submitTask(key, nil, nil) + continue + } + + default: + + switch i.stm.(type) { + case *sql.CreateStatement: + i.fail <- fmt.Errorf("Can not execute CREATE query using value '%v'", val) + case *sql.UpdateStatement: + i.fail <- fmt.Errorf("Can not execute UPDATE query using value '%v'", val) + case *sql.DeleteStatement: + i.fail <- fmt.Errorf("Can not execute DELETE query using value '%v'", val) + case *sql.RelateStatement: + i.fail <- fmt.Errorf("Can not execute RELATE query using value '%v'", val) + } + + close(i.stop) + + } + + break + + } + +} + +func (i *iterator) processQuery(ctx context.Context, key *keys.Thing, val []interface{}) { + + i.processPerms(ctx, key.NS, key.DB, key.TB) + + for _, v := range val { + + switch v := v.(type) { + + case *sql.Thing: + + // If the item is a *sql.Thing then + // this was a subquery which projected + // the ID only, and we can query the + // record further after loading it. + + if i.checkState(ctx) { + key := key.Copy() + key.TB, key.ID = v.TB, v.ID i.submitTask(key, nil, nil) continue } @@ -721,7 +766,7 @@ func (i *iterator) processQuery(ctx context.Context, key *keys.Thing, val []inte // of the data so we can process it. if i.checkState(ctx) { - i.submitTask(nil, nil, data.Consume(val)) + i.submitTask(nil, nil, data.Consume(v)) continue } @@ -737,9 +782,9 @@ func (i *iterator) processArray(ctx context.Context, key *keys.Thing, val []inte i.processPerms(ctx, key.NS, key.DB, key.TB) - for _, val := range val { + for _, v := range val { - switch val := val.(type) { + switch v := v.(type) { case *sql.Thing: @@ -748,7 +793,7 @@ func (i *iterator) processArray(ctx context.Context, key *keys.Thing, val []inte if i.checkState(ctx) { key := key.Copy() - key.ID = val.ID + key.ID = v.ID i.submitTask(key, nil, nil) continue } @@ -758,9 +803,9 @@ func (i *iterator) processArray(ctx context.Context, key *keys.Thing, val []inte // If the data item has an ID field, // then use this as the new record ID. - if fld, ok := val["id"]; ok { + if fld, ok := v["id"]; ok { - if thg, ok := val["id"].(*sql.Thing); ok { + if thg, ok := v["id"].(*sql.Thing); ok { // If the ID is a *sql.Thing then this // was a subquery, so use the ID. @@ -768,7 +813,7 @@ func (i *iterator) processArray(ctx context.Context, key *keys.Thing, val []inte if i.checkState(ctx) { key := key.Copy() key.ID = thg.ID - i.submitTask(key, nil, data.Consume(val)) + i.submitTask(key, nil, data.Consume(v)) continue } @@ -780,7 +825,7 @@ func (i *iterator) processArray(ctx context.Context, key *keys.Thing, val []inte if i.checkState(ctx) { key := key.Copy() key.ID = fld - i.submitTask(key, nil, data.Consume(val)) + i.submitTask(key, nil, data.Consume(v)) continue } @@ -794,7 +839,7 @@ func (i *iterator) processArray(ctx context.Context, key *keys.Thing, val []inte if i.checkState(ctx) { key := key.Copy() key.ID = guid.New().String() - i.submitTask(key, nil, data.Consume(val)) + i.submitTask(key, nil, data.Consume(v)) continue } diff --git a/db/relate.go b/db/relate.go index 3bb0d683..bf92fe28 100644 --- a/db/relate.go +++ b/db/relate.go @@ -60,6 +60,16 @@ func (e *executor) executeRelate(ctx context.Context, stm *sql.RelateStatement) key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.ID, ID: guid.New().String()} i.processThing(ctx, key) + // Result of subquery + case []interface{}: + key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB} + i.processOther(ctx, key, what) + + // Result of subquery with LIMIT 1 + case map[string]interface{}: + key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB} + i.processOther(ctx, key, []interface{}{what}) + } return i.Yield(ctx) diff --git a/db/update.go b/db/update.go index 6e716ca0..4a0fd222 100644 --- a/db/update.go +++ b/db/update.go @@ -65,6 +65,16 @@ func (e *executor) executeUpdate(ctx context.Context, stm *sql.UpdateStatement) key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, ID: nil} i.processBatch(ctx, key, what) + // Result of subquery + case []interface{}: + key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB} + i.processOther(ctx, key, what) + + // Result of subquery with LIMIT 1 + case map[string]interface{}: + key := &keys.Thing{KV: stm.KV, NS: stm.NS, DB: stm.DB} + i.processOther(ctx, key, []interface{}{what}) + } }