// Plan returns a IR plan for the policy query.
6204
func (p *Planner) Plan() (*ir.Policy, error) {

	for _, q := range p.queries {
		p.curr = &ir.Block{}
		defined := false

		if err := p.planQuery(q, 0, func() error {
			p.appendStmt(ir.ReturnStmt{
				Code: ir.Defined,
			})
			defined = true
			return nil
		}); err != nil {
			return nil, err
		}

		if defined {
			p.blocks = append(p.blocks, *p.curr)
		}
	}

	p.blocks = append(p.blocks, ir.Block{
		Stmts: []ir.Stmt{
			ir.ReturnStmt{
				Code: ir.Undefined,
			},
		},
	})

	policy := ir.Policy{
		Static: ir.Static{
			Strings: p.strings,
		},
		Plan: ir.Plan{
			Blocks: p.blocks,
		},
	}

	return &policy, nil
}
1144441
func (s *balanceStrategy) Plan(members map[string]ConsumerGroupMemberMetadata, topics map[string][]int32) (BalanceStrategyPlan, error) {
	// Build members by topic map
	mbt := make(map[string][]string)
	for memberID, meta := range members {
		for _, topic := range meta.Topics {
			mbt[topic] = append(mbt[topic], memberID)
		}
	}

	// Sort members for each topic
	for topic, memberIDs := range mbt {
		sort.Sort(&balanceStrategySortable{
			topic:     topic,
			memberIDs: memberIDs,
		})
	}

	// Assemble plan
	plan := make(BalanceStrategyPlan, len(members))
	for topic, memberIDs := range mbt {
		s.coreFn(plan, memberIDs, topic, topics[topic])
	}
	return plan, nil
}
202367
func NewPlan(version Version, level Level, mask Mask) (*Plan, error) {
	p, err := vplan(version)
	if err != nil {
		return nil, err
	}
	if err := fplan(level, mask, p); err != nil {
		return nil, err
	}
	if err := lplan(version, level, p); err != nil {
		return nil, err
	}
	if err := mplan(mask, p); err != nil {
		return nil, err
	}
	return p, nil
}
770623
func (qri *Map) FilterByPlan(query string, planid planbuilder.PlanType, tableName string) (newqrs *Rules) {
	qri.mu.Lock()
	defer qri.mu.Unlock()
	newqrs = New()
	for _, rules := range qri.queryRulesMap {
		newqrs.Append(rules.FilterByPlan(query, planid, tableName))
	}
	return newqrs
}
486886
func (c *IDClient) CreatePlanCost(ctx context.Context, id gomanifold.ID, planCostRequest *PlanCostRequest) (*Price, error) {
	idBytes, err := id.MarshalText()
	if err != nil {
		return nil, err
	}

	p := fmt.Sprintf("/id/plan/%s/cost", string(idBytes))

	req, err := c.backend.NewRequest(http.MethodPost, p, nil, planCostRequest)
	if err != nil {
		return nil, err
	}

	var resp Price
	_, err = c.backend.Do(ctx, req, &resp, func(code int) error {
		switch code {
		case 400, 404, 500:
			return &Error{}
		default:
			return nil
		}
	})
	if err != nil {
		return nil, err
	}

	return &resp, nil
}
145535
func (p *planner) applyPlan(plan *structs.Plan, result *structs.PlanResult, snap *state.StateSnapshot) (raft.ApplyFuture, error) {
	// Setup the update request
	req := structs.ApplyPlanResultsRequest{
		AllocUpdateRequest: structs.AllocUpdateRequest{
			Job: plan.Job,
		},
		Deployment:        result.Deployment,
		DeploymentUpdates: result.DeploymentUpdates,
		EvalID:            plan.EvalID,
	}

	preemptedJobIDs := make(map[structs.NamespacedID]struct{})
	now := time.Now().UTC().UnixNano()

	if ServersMeetMinimumVersion(p.Members(), MinVersionPlanNormalization, true) {
		// Initialize the allocs request using the new optimized log entry format.
		// Determine the minimum number of updates, could be more if there
		// are multiple updates per node
		req.AllocsStopped = make([]*structs.AllocationDiff, 0, len(result.NodeUpdate))
		req.AllocsUpdated = make([]*structs.Allocation, 0, len(result.NodeAllocation))
		req.AllocsPreempted = make([]*structs.AllocationDiff, 0, len(result.NodePreemptions))

		for _, updateList := range result.NodeUpdate {
			for _, stoppedAlloc := range updateList {
				req.AllocsStopped = append(req.AllocsStopped, normalizeStoppedAlloc(stoppedAlloc, now))
			}
		}

		for _, allocList := range result.NodeAllocation {
			req.AllocsUpdated = append(req.AllocsUpdated, allocList...)
		}

		// Set the time the alloc was applied for the first time. This can be used
		// to approximate the scheduling time.
		updateAllocTimestamps(req.AllocsUpdated, now)

		for _, preemptions := range result.NodePreemptions {
			for _, preemptedAlloc := range preemptions {
				req.AllocsPreempted = append(req.AllocsPreempted, normalizePreemptedAlloc(preemptedAlloc, now))

				// Gather jobids to create follow up evals
				appendNamespacedJobID(preemptedJobIDs, preemptedAlloc)
			}
		}
	} else {
		// COMPAT 0.11: This branch is deprecated and will only be used to support
		// application of older log entries. Expected to be removed in a future version.

		// Determine the minimum number of updates, could be more if there
		// are multiple updates per node
		minUpdates := len(result.NodeUpdate)
		minUpdates += len(result.NodeAllocation)

		// Initialize using the older log entry format for Alloc and NodePreemptions
		req.Alloc = make([]*structs.Allocation, 0, minUpdates)
		req.NodePreemptions = make([]*structs.Allocation, 0, len(result.NodePreemptions))

		for _, updateList := range result.NodeUpdate {
			req.Alloc = append(req.Alloc, updateList...)
		}
		for _, allocList := range result.NodeAllocation {
			req.Alloc = append(req.Alloc, allocList...)
		}

		for _, preemptions := range result.NodePreemptions {
			req.NodePreemptions = append(req.NodePreemptions, preemptions...)
		}

		// Set the time the alloc was applied for the first time. This can be used
		// to approximate the scheduling time.
		updateAllocTimestamps(req.Alloc, now)

		// Set modify time for preempted allocs if any
		// Also gather jobids to create follow up evals
		for _, alloc := range req.NodePreemptions {
			alloc.ModifyTime = now
			appendNamespacedJobID(preemptedJobIDs, alloc)
		}
	}

	var evals []*structs.Evaluation
	for preemptedJobID := range preemptedJobIDs {
		job, _ := p.State().JobByID(nil, preemptedJobID.Namespace, preemptedJobID.ID)
		if job != nil {
			eval := &structs.Evaluation{
				ID:          uuid.Generate(),
				Namespace:   job.Namespace,
				TriggeredBy: structs.EvalTriggerPreemption,
				JobID:       job.ID,
				Type:        job.Type,
				Priority:    job.Priority,
				Status:      structs.EvalStatusPending,
			}
			evals = append(evals, eval)
		}
	}
	req.PreemptionEvals = evals

	// Dispatch the Raft transaction
	future, err := p.raftApplyFuture(structs.ApplyPlanResultsRequestType, &req)
	if err != nil {
		return nil, err
	}

	// Optimistically apply to our state view
	if snap != nil {
		nextIdx := p.raft.AppliedIndex() + 1
		if err := snap.UpsertPlanResults(nextIdx, &req); err != nil {
			return future, err
		}
	}
	return future, nil
}
619495
func (f PolicyFunc) Do(ctx context.Context, request Request) (Response, error) {
	return f(ctx, request)
}
1232982
func (v *volumeAttachmentPlan) PlanInfo() (VolumeAttachmentPlanInfo, error) {
	if v.doc.PlanInfo == nil {
		return VolumeAttachmentPlanInfo{}, errors.NotProvisionedf("volume attachment plan %q on %q", v.doc.Volume, v.doc.Machine)
	}
	return *v.doc.PlanInfo, nil
}
1350064
func (s *SchedulePolicyServer) Update(
	ctx context.Context,
	req *api.SdkSchedulePolicyUpdateRequest,
) (*api.SdkSchedulePolicyUpdateResponse, error) {
	if s.cluster() == nil {
		return nil, status.Error(codes.Unavailable, "Resource has not been initialized")
	}

	if req.GetSchedulePolicy() == nil {
		return nil, status.Error(codes.InvalidArgument, "SchedulePolicy object cannot be nil")
	} else if len(req.GetSchedulePolicy().GetName()) == 0 {
		return nil, status.Error(codes.InvalidArgument, "Must supply Schedule name")
	} else if req.GetSchedulePolicy().GetSchedules() == nil ||
		len(req.GetSchedulePolicy().GetSchedules()) == 0 {
		return nil, status.Error(codes.InvalidArgument, "Must supply Schedule")
	}

	for _, sdkSched := range req.GetSchedulePolicy().GetSchedules() {
		if sdkSched.GetRetain() < 1 {
			return nil, status.Error(codes.InvalidArgument, "Must retain more than 0")
		}
	}
	out, err := sdkSchedToRetainInternalSpecYamlByte(req.GetSchedulePolicy().GetSchedules())
	if err != nil {
		return nil, err
	}
	err = s.cluster().SchedPolicyUpdate(req.GetSchedulePolicy().GetName(), string(out))
	if err != nil {
		if err == kvdb.ErrNotFound {
			return nil, status.Errorf(
				codes.NotFound,
				"Schedule policy %s not found",
				req.GetSchedulePolicy().GetName())
		}
		return nil, status.Errorf(
			codes.Internal,
			"Failed to update schedule policy: %v",
			err.Error())
	}

	return &api.SdkSchedulePolicyUpdateResponse{}, err
}
406792
func (rp *ReplicatorPlan) buildExecutionPlan(fieldEvent *binlogdatapb.FieldEvent) (*TablePlan, error) {
	prelim := rp.TablePlans[fieldEvent.TableName]
	if prelim == nil {
		// Unreachable code.
		return nil, fmt.Errorf("plan not found for %s", fieldEvent.TableName)
	}
	if prelim.Insert != nil {
		tplanv := *prelim
		tplanv.Fields = fieldEvent.Fields
		return &tplanv, nil
	}
	// select * construct was used. We need to use the field names.
	tplan, err := rp.buildFromFields(prelim.TargetName, fieldEvent.Fields)
	if err != nil {
		return nil, err
	}
	tplan.Fields = fieldEvent.Fields
	return tplan, nil
}
670874
func NewPlan(changes *plans.Changes) *Plan {
	log.Printf("[TRACE] NewPlan for %#v", changes)
	ret := &Plan{}
	if changes == nil {
		// Nothing to do!
		return ret
	}

	for _, rc := range changes.Resources {
		addr := rc.Addr
		log.Printf("[TRACE] NewPlan found %s (%s)", addr, rc.Action)
		dataSource := addr.Resource.Resource.Mode == addrs.DataResourceMode

		// We create "delete" actions for data resources so we can clean
		// up their entries in state, but this is an implementation detail
		// that users shouldn't see.
		if dataSource && rc.Action == plans.Delete {
			continue
		}

		// For now we'll shim this to work with our old types.
		// TODO: Update for the new plan types, ideally also switching over to
		// a structural diff renderer instead of a flat renderer.
		did := &InstanceDiff{
			Addr:   terraform.NewLegacyResourceInstanceAddress(addr),
			Action: rc.Action,
		}

		if rc.DeposedKey != states.NotDeposed {
			did.Deposed = true
		}

		// Since this is just a temporary stub implementation on the way
		// to us replacing this with the structural diff renderer, we currently
		// don't include any attributes here.
		// FIXME: Implement the structural diff renderer to replace this
		// codepath altogether.

		ret.Resources = append(ret.Resources, did)
	}

	// Sort the instance diffs by their addresses for display.
	sort.Slice(ret.Resources, func(i, j int) bool {
		iAddr := ret.Resources[i].Addr
		jAddr := ret.Resources[j].Addr
		return iAddr.Less(jAddr)
	})

	return ret
}
133971
func (plan *Plan) filter(values []sqltypes.Value) (bool, []sqltypes.Value, error) {
	result := make([]sqltypes.Value, len(plan.ColExprs))
	for i, colExpr := range plan.ColExprs {
		result[i] = values[colExpr.ColNum]
	}
	if plan.Vindex == nil {
		return true, result, nil
	}

	// Filter by Vindex.
	destinations, err := plan.Vindex.Map(nil, []sqltypes.Value{result[plan.VindexColumn]})
	if err != nil {
		return false, nil, err
	}
	if len(destinations) != 1 {
		return false, nil, fmt.Errorf("mapping row to keyspace id returned an invalid array of destinations: %v", key.DestinationsString(destinations))
	}
	ksid, ok := destinations[0].(key.DestinationKeyspaceID)
	if !ok || len(ksid) == 0 {
		return false, nil, fmt.Errorf("could not map %v to a keyspace id, got destination %v", result[plan.VindexColumn], destinations[0])
	}
	if !key.KeyRangeContains(plan.KeyRange, ksid) {
		return false, nil, nil
	}
	return true, result, nil
}
526850
func Get(region string) (frequencyPlan FrequencyPlan, err error) {
	if fp, ok := frequencyPlans[region]; ok {
		return fp, nil
	}
	switch region {
	case pb_lorawan.FrequencyPlan_EU_863_870.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.EU_863_870, false, lorawan.DwellTimeNoLimit)
		// TTN frequency plan includes extra channels next to the default channels:
		frequencyPlan.UplinkChannels = []lora.Channel{
			lora.Channel{Frequency: 868100000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 868300000, DataRates: []int{0, 1, 2, 3, 4, 5, 6}}, // Also SF7BW250
			lora.Channel{Frequency: 868500000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 867100000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 867300000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 867500000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 867700000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 867900000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 868800000, DataRates: []int{7}}, // FSK 50kbps
		}
		frequencyPlan.DownlinkChannels = frequencyPlan.UplinkChannels
		frequencyPlan.CFList = &lorawan.CFList{867100000, 867300000, 867500000, 867700000, 867900000}
		frequencyPlan.ADR = &ADRConfig{MinDataRate: 0, MaxDataRate: 5, MinTXPower: 2, MaxTXPower: 14, StepTXPower: 3}
		frequencyPlan.RX2DataRate = viper.GetInt("eu-rx2-dr")
	case pb_lorawan.FrequencyPlan_US_902_928.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.US_902_928, false, lorawan.DwellTime400ms)
		fsb := viper.GetInt("us-fsb") // If this is 1, enables 903.9-905.3/200 kHz, 904.6/500kHz channels, etc.
		for channel := 0; channel < 72; channel++ {
			if (channel < fsb*8 || channel >= (fsb+1)*8) && channel != fsb+64 {
				frequencyPlan.DisableUplinkChannel(channel)
			}
		}
		frequencyPlan.ADR = &ADRConfig{MinDataRate: 0, MaxDataRate: 3, MinTXPower: 10, MaxTXPower: 20, StepTXPower: 2}
	case pb_lorawan.FrequencyPlan_CN_779_787.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.CN_779_787, false, lorawan.DwellTimeNoLimit)
	case pb_lorawan.FrequencyPlan_EU_433.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.EU_433, false, lorawan.DwellTimeNoLimit)
	case pb_lorawan.FrequencyPlan_AU_915_928.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.AU_915_928, false, lorawan.DwellTime400ms)
		fsb := viper.GetInt("au-fsb") // If this is 1, enables 916.8-918.2/200 kHz, 917.5/500kHz channels, etc.
		for channel := 0; channel < 72; channel++ {
			if (channel < fsb*8 || channel >= (fsb+1)*8) && channel != fsb+64 {
				frequencyPlan.DisableUplinkChannel(channel)
			}
		}
		frequencyPlan.ADR = &ADRConfig{MinDataRate: 0, MaxDataRate: 5, MinTXPower: 10, MaxTXPower: 20, StepTXPower: 2}
	case pb_lorawan.FrequencyPlan_CN_470_510.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.CN_470_510, false, lorawan.DwellTimeNoLimit)
	case pb_lorawan.FrequencyPlan_AS_923.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.AS_923, false, lorawan.DwellTime400ms)
		frequencyPlan.ADR = &ADRConfig{MinDataRate: 0, MaxDataRate: 5, MinTXPower: 2, MaxTXPower: 14, StepTXPower: 2}
	case pb_lorawan.FrequencyPlan_AS_920_923.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.AS_923, false, lorawan.DwellTime400ms)
		frequencyPlan.UplinkChannels = []lora.Channel{
			lora.Channel{Frequency: 923200000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 923400000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922200000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922400000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922600000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922800000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 923000000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922000000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922100000, DataRates: []int{6}},
			lora.Channel{Frequency: 921800000, DataRates: []int{7}},
		}
		frequencyPlan.DownlinkChannels = frequencyPlan.UplinkChannels
		frequencyPlan.CFList = &lorawan.CFList{922200000, 922400000, 922600000, 922800000, 923000000}
		frequencyPlan.ADR = &ADRConfig{MinDataRate: 0, MaxDataRate: 5, MinTXPower: 2, MaxTXPower: 14, StepTXPower: 2}
	case pb_lorawan.FrequencyPlan_AS_923_925.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.AS_923, false, lorawan.DwellTime400ms)
		frequencyPlan.UplinkChannels = []lora.Channel{
			lora.Channel{Frequency: 923200000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 923400000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 923600000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 923800000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 924000000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 924200000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 924400000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 924600000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 924500000, DataRates: []int{6}},
			lora.Channel{Frequency: 924800000, DataRates: []int{7}},
		}
		frequencyPlan.DownlinkChannels = frequencyPlan.UplinkChannels
		frequencyPlan.CFList = &lorawan.CFList{923600000, 923800000, 924000000, 924200000, 924400000}
		frequencyPlan.ADR = &ADRConfig{MinDataRate: 0, MaxDataRate: 5, MinTXPower: 2, MaxTXPower: 14, StepTXPower: 2}
	case pb_lorawan.FrequencyPlan_KR_920_923.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.KR_920_923, false, lorawan.DwellTimeNoLimit)
		// TTN frequency plan includes extra channels next to the default channels:
		frequencyPlan.UplinkChannels = []lora.Channel{
			lora.Channel{Frequency: 922100000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922300000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922500000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922700000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 922900000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 923100000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 923300000, DataRates: []int{0, 1, 2, 3, 4, 5}},
		}
		frequencyPlan.DownlinkChannels = frequencyPlan.UplinkChannels
		frequencyPlan.CFList = &lorawan.CFList{922700000, 922900000, 923100000, 923300000, 0}
		frequencyPlan.ADR = &ADRConfig{MinDataRate: 0, MaxDataRate: 5, MinTXPower: 2, MaxTXPower: 14, StepTXPower: 2}
	case pb_lorawan.FrequencyPlan_IN_865_867.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.IN_865_867, false, lorawan.DwellTimeNoLimit)
	case pb_lorawan.FrequencyPlan_RU_864_870.String():
		frequencyPlan.Band, err = lora.GetConfig(lora.RU_864_870, false, lorawan.DwellTimeNoLimit)
		// Here channels from recommended list for Russia are set which are used by LoRaWAN networks in Russia
		// Recommended frequency plan includes extra channels next to the default channels:
		frequencyPlan.UplinkChannels = []lora.Channel{
			lora.Channel{Frequency: 868900000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 869100000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 864100000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 864300000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 864500000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 864700000, DataRates: []int{0, 1, 2, 3, 4, 5}},
			lora.Channel{Frequency: 864900000, DataRates: []int{0, 1, 2, 3, 4, 5}},
		}
		frequencyPlan.DownlinkChannels = frequencyPlan.UplinkChannels
		frequencyPlan.CFList = &lorawan.CFList{864100000, 864300000, 864500000, 864700000, 864900000}
		frequencyPlan.ADR = &ADRConfig{MinDataRate: 0, MaxDataRate: 5, MinTXPower: 2, MaxTXPower: 14, StepTXPower: 3}
	default:
		err = errors.NewErrInvalidArgument("Frequency Band", "unknown")
	}
	return
}
210217
func (i DatabaseInventory) PlanVersion() int64 {
	if len(i.Collections) == 0 {
		return 0
	}
	return i.Collections[0].PlanVersion
}
1042005
func (abp *attrPolicyBuilder) Globally() *Policy {

	for _, attr := range abp.attrNames {
		if _, ok := abp.p.globalAttrs[attr]; !ok {
			abp.p.globalAttrs[attr] = attrPolicy{}
		}

		ap := attrPolicy{}
		if abp.regexp != nil {
			ap.regexp = abp.regexp
		}

		abp.p.globalAttrs[attr] = ap
	}

	return abp.p
}
1325913
func (self *PlanClient) Update(id string, newName string) (*Plan, error) {
	values := url.Values{"name": {newName}}
	plan := Plan{}
	path := "/v1/plans/" + url.QueryEscape(id)
	err := query("POST", path, values, &plan)
	return &plan, err
}
1085127
func (qe *QueryEngine) GetPlan(ctx context.Context, logStats *tabletenv.LogStats, sql string, skipQueryPlanCache bool) (*TabletPlan, error) {
	span, ctx := trace.NewSpan(ctx, "QueryEngine.GetPlan")
	defer span.Finish()

	if plan := qe.getQuery(sql); plan != nil {
		return plan, nil
	}

	// Obtain read lock to prevent schema from changing while
	// we build a plan. The read lock allows multiple identical
	// queries to build the same plan. One of them will win by
	// updating the query cache and prevent future races. Due to
	// this, query stats reporting may not be accurate, but it's
	// acceptable because those numbers are best effort.
	qe.mu.RLock()
	defer qe.mu.RUnlock()
	statement, err := sqlparser.Parse(sql)
	if err != nil {
		return nil, err
	}
	splan, err := planbuilder.Build(statement, qe.tables)
	if err != nil {
		return nil, err
	}
	plan := &TabletPlan{Plan: splan}
	plan.Rules = qe.queryRuleSources.FilterByPlan(sql, plan.PlanID, plan.TableName().String())
	plan.buildAuthorized()
	if plan.PlanID.IsSelect() {
		if plan.FieldQuery != nil {
			conn, err := qe.getQueryConn(ctx)
			if err != nil {
				return nil, err
			}
			defer conn.Recycle()

			sql := plan.FieldQuery.Query
			start := time.Now()
			r, err := conn.Exec(ctx, sql, 1, true)
			logStats.AddRewrittenSQL(sql, start)
			if err != nil {
				return nil, err
			}
			plan.Fields = r.Fields
		}
	} else if plan.PlanID == planbuilder.PlanDDL || plan.PlanID == planbuilder.PlanSet {
		return plan, nil
	}
	if !skipQueryPlanCache && !sqlparser.SkipQueryPlanCacheDirective(statement) {
		qe.plans.Set(sql, plan)
	}
	return plan, nil
}