2023-04-07 11:00:49 +03:00
|
|
|
package libsq
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"github.com/neilotoole/sq/libsq/ast/render"
|
|
|
|
)
|
|
|
|
|
2023-07-03 18:34:19 +03:00
|
|
|
// prepare prepares the pipeline to execute queryModel.
|
2024-01-15 04:45:34 +03:00
|
|
|
// When this method returns, targetGrip and targetSQL will be set,
|
2023-04-07 11:00:49 +03:00
|
|
|
// as will any tasks (which may be empty). The tasks must be executed
|
2024-01-15 04:45:34 +03:00
|
|
|
// against targetGrip before targetSQL is executed (the pipeline.execute
|
2023-04-07 11:00:49 +03:00
|
|
|
// method does this work).
|
2023-07-03 18:34:19 +03:00
|
|
|
func (p *pipeline) prepare(ctx context.Context, qm *queryModel) error {
|
2023-11-20 09:44:36 +03:00
|
|
|
var err error
|
|
|
|
|
|
|
|
frags := &render.Fragments{}
|
2023-04-07 11:00:49 +03:00
|
|
|
|
2023-07-03 18:34:19 +03:00
|
|
|
// After this switch, p.rc will be set.
|
|
|
|
switch {
|
|
|
|
case qm.Table == nil:
|
|
|
|
if err = p.prepareNoTable(ctx, qm); err != nil {
|
2023-06-18 04:28:11 +03:00
|
|
|
return err
|
|
|
|
}
|
2023-07-03 18:34:19 +03:00
|
|
|
case len(qm.Joins) > 0:
|
|
|
|
jc := &joinClause{leftTbl: qm.Table, joins: qm.Joins}
|
2024-01-15 04:45:34 +03:00
|
|
|
if frags.From, p.targetGrip, err = p.prepareFromJoin(ctx, jc); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
2023-07-03 18:34:19 +03:00
|
|
|
default:
|
2024-01-15 04:45:34 +03:00
|
|
|
if frags.From, p.targetGrip, err = p.prepareFromTable(ctx, qm.Table); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-20 09:44:36 +03:00
|
|
|
p.rc.Fragments = frags
|
2023-07-03 18:34:19 +03:00
|
|
|
rndr := p.rc.Renderer
|
|
|
|
if frags.Columns, err = rndr.SelectCols(p.rc, qm.Cols); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if qm.Distinct != nil {
|
2023-07-03 18:34:19 +03:00
|
|
|
if frags.Distinct, err = rndr.Distinct(p.rc, qm.Distinct); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if qm.Range != nil {
|
2023-07-03 18:34:19 +03:00
|
|
|
if frags.Range, err = rndr.Range(p.rc, qm.Range); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if qm.Where != nil {
|
2023-07-03 18:34:19 +03:00
|
|
|
if frags.Where, err = rndr.Where(p.rc, qm.Where); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if qm.OrderBy != nil {
|
2023-07-03 18:34:19 +03:00
|
|
|
if frags.OrderBy, err = rndr.OrderBy(p.rc, qm.OrderBy); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if qm.GroupBy != nil {
|
2023-07-03 18:34:19 +03:00
|
|
|
if frags.GroupBy, err = rndr.GroupBy(p.rc, qm.GroupBy); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-22 20:56:19 +03:00
|
|
|
if qm.Having != nil {
|
|
|
|
if frags.Having, err = rndr.Having(p.rc, qm.Having); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-20 09:44:36 +03:00
|
|
|
for _, fn := range rndr.PreRender {
|
|
|
|
if err = fn(p.rc, frags); err != nil {
|
2023-04-07 11:00:49 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-20 09:44:36 +03:00
|
|
|
if p.targetSQL, err = rndr.Render(p.rc, frags); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
p.qc.PreExecStmts = append(p.qc.PreExecStmts, frags.PreExecStmts...)
|
|
|
|
p.qc.PostExecStmts = append(p.qc.PostExecStmts, frags.PostExecStmts...)
|
|
|
|
|
|
|
|
return nil
|
2023-04-07 11:00:49 +03:00
|
|
|
}
|