diff --git a/dax/queryer/orchestrator.go b/dax/queryer/orchestrator.go index 758140557..f3151972b 100644 --- a/dax/queryer/orchestrator.go +++ b/dax/queryer/orchestrator.go @@ -2530,7 +2530,21 @@ func (o *orchestrator) translateCall(ctx context.Context, c *pql.Call, tableKeye // This also applies to all child calls. if callIndex := c.CallIndex(); callIndex != "" { index = callIndex - tableKeyer = dax.StringTableKeyer(index) + // TODO(tlt): checking for prefix like this is bad form. Ideally, the + // argument stored in the Call.Args map would be of type TableKey + // (currently they are restricted to type: string). In that case we + // could just pass it through without doing this conversion. (This would + // require changing the logic in Queryer.convertIndex() to set "index" + // to a TableKeyer). + if strings.HasPrefix(index, dax.PrefixTable+dax.TableKeyDelimiter) { + qtid, err := dax.QualifiedTableIDFromKey(index) + if err != nil { + return nil, errors.Wrapf(err, "getting qtid from key: %s", index) + } + tableKeyer = qtid + } else { + tableKeyer = dax.StringTableKeyer(index) + } } idx, err := o.schemaIndexInfo(ctx, tableKeyer) @@ -3510,6 +3524,11 @@ func (o *orchestrator) schemaFieldInfo(ctx context.Context, tableKeyer dax.Table tbl = &v.Table case *dax.Table: tbl = v + case dax.QualifiedTableID: + tbl, err = o.schema.TableByID(ctx, v.ID) + if err != nil { + return nil, errors.Wrapf(err, "getting table by id: %s", v.ID) + } case dax.StringTableKeyer: tbl, err = o.schema.TableByName(ctx, dax.TableName(v)) if err != nil { @@ -3537,6 +3556,11 @@ func (o *orchestrator) schemaIndexInfo(ctx context.Context, tableKeyer dax.Table tbl = &v.Table case *dax.Table: tbl = v + case dax.QualifiedTableID: + tbl, err = o.schema.TableByID(ctx, v.ID) + if err != nil { + return nil, errors.Wrapf(err, "getting table by id: %s", v.ID) + } case dax.StringTableKeyer: tbl, err = o.schema.TableByName(ctx, dax.TableName(v)) if err != nil { diff --git a/dax/queryer/queryer.go b/dax/queryer/queryer.go index 365116aad..09b976c5e 100644 --- a/dax/queryer/queryer.go +++ b/dax/queryer/queryer.go @@ -244,6 +244,28 @@ func (q *Queryer) parseAndQueryPQL(ctx context.Context, qual dax.TableQualifier, return q.QueryPQL(ctx, qual, dax.TableName(table), query) } +// convertIndex tries to covert any "index" specified in the call.Args map to a +// TableKeyer. Note, since the Call.CallIndex() method currently only looks for +// strings, we can't just set the value to a TableKeyer; we have to set it to +// the equivalent string and then parse it back out later. A TODO would be to +// modify Call.CallIndex() to be TableKeyer aware. I didn't do that along with +// these changes because I'm not sure if we want to introduce dax types into the +// pql package. +func (q *Queryer) convertIndex(ctx context.Context, qual dax.TableQualifier, call *featurebase_pql.Call) { + if index := call.CallIndex(); index != "" { + qtbl, err := q.schemar.TableByName(ctx, qual, dax.TableName(index)) + if err != nil { + return + } + call.Args["index"] = string(qtbl.Key()) + } + + // Apply to children. + for _, child := range call.Children { + q.convertIndex(ctx, qual, child) + } +} + func (q *Queryer) QueryPQL(ctx context.Context, qual dax.TableQualifier, table dax.TableName, pql string) (*featurebase.WireQueryResponse, error) { // Parse the pql into a pql.Query containing []pql.Call. qry, err := featurebase_pql.NewParser(strings.NewReader(pql)).Parse() @@ -254,6 +276,9 @@ func (q *Queryer) QueryPQL(ctx context.Context, qual dax.TableQualifier, table d return nil, errors.Errorf("must have exactly 1 query, but got: %+v", qry.Calls) } + // Replace any "index" arguments within the PQL with a TableKey. + q.convertIndex(ctx, qual, qry.Calls[0]) + qtbl, err := q.schemar.TableByName(ctx, qual, dax.TableName(table)) if err != nil { return nil, errors.Wrap(err, "converting index to qualified table") @@ -267,10 +292,10 @@ func (q *Queryer) QueryPQL(ctx context.Context, qual dax.TableQualifier, table d return nil, errors.Errorf("expected single result but got %+v", results.Results) } - return PQLResultToQueryResult(results.Results[0]) + return pqlResultToQueryResult(results.Results[0]) } -func PQLResultToQueryResult(pqlResult interface{}) (*featurebase.WireQueryResponse, error) { +func pqlResultToQueryResult(pqlResult interface{}) (*featurebase.WireQueryResponse, error) { toTabler, err := server.ToTablerWrapper(pqlResult) if err != nil { return nil, errors.Wrap(err, "wrapping as type ToTabler") diff --git a/sql3/test/defs/defs_join.go b/sql3/test/defs/defs_join.go index 49d156070..d1269fb18 100644 --- a/sql3/test/defs/defs_join.go +++ b/sql3/test/defs/defs_join.go @@ -28,7 +28,7 @@ var joinTestsOrders = TableTest{ "orders", srcHdrs( srcHdr("_id", fldTypeID), - srcHdr("userid", fldTypeID), + srcHdr("userid", fldTypeInt), srcHdr("price", fldTypeDecimal2), ), srcRows( @@ -103,4 +103,18 @@ var joinTests = TableTest{ Compare: CompareExactOrdered, }, }, + PQLTests: []PQLTest{ + { + name: "distinctjoin", + Table: "users", + PQLs: []string{"Intersect(Distinct(Row(price > 10), index=orders, field=userid))"}, + ExpHdrs: hdrs( + hdr("_id", fldTypeID), + ), + ExpRows: rows( + row(int64(1)), + row(int64(2)), + ), + }, + }, }