1//  Copyright (c) 2014 Couchbase, Inc.
2//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
3//  except in compliance with the License. You may obtain a copy of the License at
4//    http://www.apache.org/licenses/LICENSE-2.0
5//  Unless required by applicable law or agreed to in writing, software distributed under the
6//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
7//  either express or implied. See the License for the specific language governing permissions
8//  and limitations under the License.
9
10package expression
11
12import (
13	"fmt"
14
15	"github.com/couchbase/query/errors"
16	"github.com/couchbase/query/value"
17)
18
19/*
20Bit flags for formalizer flags
21*/
22const (
23	FORM_MAP_SELF     = 1 << iota // Map SELF to keyspace: used in sarging index
24	FORM_MAP_KEYSPACE             // Map keyspace to SELF: used in creating index
25	FORM_INDEX_SCOPE              // formalizing index key or index condition
26)
27
28/*
29Convert expressions to full form qualified by keyspace aliases.
30*/
31type Formalizer struct {
32	MapperBase
33
34	keyspace    string
35	allowed     *value.ScopeValue
36	identifiers *value.ScopeValue
37	aliases     *value.ScopeValue
38	flags       uint32
39}
40
41func NewFormalizer(keyspace string, parent *Formalizer) *Formalizer {
42	return newFormalizer(keyspace, parent, false, false)
43}
44
45func NewSelfFormalizer(keyspace string, parent *Formalizer) *Formalizer {
46	return newFormalizer(keyspace, parent, true, false)
47}
48
49func NewKeyspaceFormalizer(keyspace string, parent *Formalizer) *Formalizer {
50	return newFormalizer(keyspace, parent, false, true)
51}
52
53func newFormalizer(keyspace string, parent *Formalizer, mapSelf, mapKeyspace bool) *Formalizer {
54	var pv, av value.Value
55	if parent != nil {
56		pv = parent.allowed
57		av = parent.aliases
58		mapSelf = mapSelf || parent.mapSelf()
59		mapKeyspace = mapKeyspace || parent.mapKeyspace()
60	}
61
62	flags := uint32(0)
63	if mapSelf {
64		flags |= FORM_MAP_SELF
65	}
66	if mapKeyspace {
67		flags |= FORM_MAP_KEYSPACE
68	}
69
70	rv := &Formalizer{
71		keyspace:    keyspace,
72		allowed:     value.NewScopeValue(make(map[string]interface{}), pv),
73		identifiers: value.NewScopeValue(make(map[string]interface{}, 64), nil),
74		aliases:     value.NewScopeValue(make(map[string]interface{}), av),
75		flags:       flags,
76	}
77
78	if !mapKeyspace && keyspace != "" {
79		rv.SetAllowedAlias(keyspace, true)
80	}
81
82	rv.mapper = rv
83	return rv
84}
85
86func (this *Formalizer) mapSelf() bool {
87	return (this.flags & FORM_MAP_SELF) != 0
88}
89
90func (this *Formalizer) mapKeyspace() bool {
91	return (this.flags & FORM_MAP_KEYSPACE) != 0
92}
93
94func (this *Formalizer) indexScope() bool {
95	return (this.flags & FORM_INDEX_SCOPE) != 0
96}
97
98func (this *Formalizer) SetIndexScope() {
99	this.flags |= FORM_INDEX_SCOPE
100}
101
102func (this *Formalizer) ClearIndexScope() {
103	this.flags &^= FORM_INDEX_SCOPE
104}
105
106func (this *Formalizer) VisitAny(expr *Any) (interface{}, error) {
107	err := this.PushBindings(expr.Bindings(), true)
108	if err != nil {
109		return nil, err
110	}
111
112	defer this.PopBindings()
113
114	err = expr.MapChildren(this)
115	if err != nil {
116		return nil, err
117	}
118
119	return expr, nil
120}
121
122func (this *Formalizer) VisitEvery(expr *Every) (interface{}, error) {
123	err := this.PushBindings(expr.Bindings(), true)
124	if err != nil {
125		return nil, err
126	}
127
128	defer this.PopBindings()
129
130	err = expr.MapChildren(this)
131	if err != nil {
132		return nil, err
133	}
134
135	return expr, nil
136}
137
138func (this *Formalizer) VisitAnyEvery(expr *AnyEvery) (interface{}, error) {
139	err := this.PushBindings(expr.Bindings(), true)
140	if err != nil {
141		return nil, err
142	}
143
144	defer this.PopBindings()
145
146	err = expr.MapChildren(this)
147	if err != nil {
148		return nil, err
149	}
150
151	return expr, nil
152}
153
154func (this *Formalizer) VisitArray(expr *Array) (interface{}, error) {
155	err := this.PushBindings(expr.Bindings(), true)
156	if err != nil {
157		return nil, err
158	}
159
160	defer this.PopBindings()
161
162	err = expr.MapChildren(this)
163	if err != nil {
164		return nil, err
165	}
166
167	return expr, nil
168}
169
170func (this *Formalizer) VisitFirst(expr *First) (interface{}, error) {
171	err := this.PushBindings(expr.Bindings(), true)
172	if err != nil {
173		return nil, err
174	}
175
176	defer this.PopBindings()
177
178	err = expr.MapChildren(this)
179	if err != nil {
180		return nil, err
181	}
182
183	return expr, nil
184}
185
186func (this *Formalizer) VisitObject(expr *Object) (interface{}, error) {
187	err := this.PushBindings(expr.Bindings(), true)
188	if err != nil {
189		return nil, err
190	}
191
192	defer this.PopBindings()
193
194	err = expr.MapChildren(this)
195	if err != nil {
196		return nil, err
197	}
198
199	return expr, nil
200}
201
202/*
203Formalize Identifier.
204*/
205func (this *Formalizer) VisitIdentifier(expr *Identifier) (interface{}, error) {
206	identifier := expr.Identifier()
207
208	ident_val, ok := this.allowed.Field(identifier)
209	if ok {
210		// if sarging for index, for index keys or index conditions,
211		// don't match with keyspace alias
212		// (i.e., don't match an index key name with a keyspace alias)
213		// however if this is a keyspace alias added in previous formalization
214		// process then treat it as a keyspace alias
215		ident_flags := uint32(ident_val.ActualForIndex().(int64))
216		keyspace_flags := ident_flags & IDENT_IS_KEYSPACE
217		variable_flags := ident_flags & IDENT_IS_VARIABLE
218		unnest_flags := ident_flags & IDENT_IS_UNNEST_ALIAS
219		if !this.indexScope() || keyspace_flags == 0 || expr.IsKeyspaceAlias() {
220			this.identifiers.SetField(identifier, ident_val)
221			// for user specified keyspace alias (such as alias.c1)
222			// set flag to indicate it's keyspace
223			if keyspace_flags != 0 && !expr.IsKeyspaceAlias() {
224				expr.SetKeyspaceAlias(true)
225			}
226			if variable_flags != 0 && !expr.IsBindingVariable() {
227				expr.SetBindingVariable(true)
228			}
229			if unnest_flags != 0 && !expr.IsUnnestAlias() {
230				expr.SetUnnestAlias(true)
231			}
232			return expr, nil
233		}
234	}
235
236	if this.keyspace == "" {
237		return nil, fmt.Errorf("Ambiguous reference to field %v.", identifier)
238	}
239
240	if this.mapKeyspace() {
241		if identifier == this.keyspace {
242			return SELF, nil
243		} else {
244			return expr, nil
245		}
246	} else {
247		keyspaceIdent := NewIdentifier(this.keyspace)
248		keyspaceIdent.SetKeyspaceAlias(true)
249		return NewField(keyspaceIdent, NewFieldName(identifier, expr.CaseInsensitive())),
250			nil
251	}
252}
253
254/*
255Formalize SELF functions defined on indexes.
256*/
257func (this *Formalizer) VisitSelf(expr *Self) (interface{}, error) {
258	if this.mapSelf() {
259		keyspaceIdent := NewIdentifier(this.keyspace)
260		keyspaceIdent.SetKeyspaceAlias(true)
261		return keyspaceIdent, nil
262	} else {
263		return expr, nil
264	}
265}
266
267/*
268Formalize META() functions defined on indexes.
269*/
270func (this *Formalizer) VisitFunction(expr Function) (interface{}, error) {
271	if !this.mapKeyspace() {
272		meta, ok := expr.(*Meta)
273		if ok && len(meta.Operands()) == 0 {
274			if this.keyspace != "" {
275				keyspaceIdent := NewIdentifier(this.keyspace)
276				keyspaceIdent.SetKeyspaceAlias(true)
277				return NewMeta(keyspaceIdent), nil
278			} else {
279				return nil, errors.NewAmbiguousMetaError()
280			}
281		}
282	}
283
284	return expr, expr.MapChildren(this.mapper)
285}
286
287/*
288Visitor method for Subqueries. Call formalize.
289*/
290func (this *Formalizer) VisitSubquery(expr Subquery) (interface{}, error) {
291	err := expr.Formalize(this)
292	if err != nil {
293		return nil, err
294	}
295
296	return expr, nil
297}
298
299/*
300Create new scope containing bindings.
301*/
302
303func (this *Formalizer) PushBindings(bindings Bindings, push bool) (err error) {
304	allowed := this.allowed
305	identifiers := this.identifiers
306	aliases := this.aliases
307
308	if push {
309		allowed = value.NewScopeValue(make(map[string]interface{}, len(bindings)), this.allowed)
310		identifiers = value.NewScopeValue(make(map[string]interface{}, 16), this.identifiers)
311		aliases = value.NewScopeValue(make(map[string]interface{}, len(bindings)), this.aliases)
312	}
313
314	var expr Expression
315	var ident_flags uint32
316	for _, b := range bindings {
317		if ident_val, ok := allowed.Field(b.Variable()); ok {
318			ident_flags = uint32(ident_val.ActualForIndex().(int64))
319			tmp_flags1 := ident_flags & IDENT_IS_KEYSPACE
320			tmp_flags2 := ident_flags &^ IDENT_IS_KEYSPACE
321			// when sarging index keys, allow variables used in index definition
322			// to be the same as a keyspace alias
323			if !this.indexScope() || tmp_flags1 == 0 || tmp_flags2 != 0 {
324				err = fmt.Errorf("Duplicate variable %v already in scope.", b.Variable())
325				return
326			}
327		} else {
328			ident_flags = 0
329		}
330
331		ident_flags |= IDENT_IS_VARIABLE
332		ident_val := value.NewValue(ident_flags)
333		allowed.SetField(b.Variable(), ident_val)
334		aliases.SetField(b.Variable(), ident_val)
335
336		if b.NameVariable() != "" {
337			if ident_val, ok := allowed.Field(b.NameVariable()); ok {
338				ident_flags = uint32(ident_val.ActualForIndex().(int64))
339				tmp_flags1 := ident_flags & IDENT_IS_KEYSPACE
340				tmp_flags2 := ident_flags &^ IDENT_IS_KEYSPACE
341				if !this.indexScope() || tmp_flags1 == 0 || tmp_flags2 != 0 {
342					err = fmt.Errorf("Duplicate variable %v already in scope.", b.NameVariable())
343					return
344				}
345			} else {
346				ident_flags = 0
347			}
348
349			ident_flags |= IDENT_IS_VARIABLE
350			ident_val := value.NewValue(ident_flags)
351			allowed.SetField(b.NameVariable(), ident_val)
352			aliases.SetField(b.NameVariable(), ident_val)
353		}
354
355		expr, err = this.Map(b.Expression())
356		if err != nil {
357			return
358		}
359
360		b.SetExpression(expr)
361	}
362
363	if push {
364		this.allowed = allowed
365		this.identifiers = identifiers
366		this.aliases = aliases
367	}
368	return
369}
370
371/*
372Restore scope to parent's scope.
373*/
374func (this *Formalizer) PopBindings() {
375
376	currLevelAllowed := this.Allowed().GetValue().Fields()
377	currLevelIndentfiers := this.Identifiers().GetValue().Fields()
378
379	this.allowed = this.allowed.Parent().(*value.ScopeValue)
380	this.identifiers = this.identifiers.Parent().(*value.ScopeValue)
381	this.aliases = this.aliases.Parent().(*value.ScopeValue)
382
383	// Identifiers that are used in current level but not defined in the current level scope move to parent
384	for ident, _ := range currLevelIndentfiers {
385		if currLevelAllowed != nil {
386			if ident_val, ok := currLevelAllowed[ident]; !ok {
387				this.identifiers.SetField(ident, ident_val)
388			}
389		}
390	}
391}
392
393func (this *Formalizer) Copy() *Formalizer {
394	f := NewFormalizer(this.keyspace, nil)
395	f.allowed = this.allowed.Copy().(*value.ScopeValue)
396	f.identifiers = this.identifiers.Copy().(*value.ScopeValue)
397	f.aliases = this.aliases.Copy().(*value.ScopeValue)
398	f.flags = this.flags
399	return f
400}
401
402func (this *Formalizer) SetKeyspace(keyspace string) {
403	this.keyspace = keyspace
404
405	if !this.mapKeyspace() && keyspace != "" {
406		this.SetAllowedAlias(keyspace, true)
407	}
408}
409
410func (this *Formalizer) Keyspace() string {
411	return this.keyspace
412}
413
414func (this *Formalizer) Allowed() *value.ScopeValue {
415	return this.allowed
416}
417
418func (this *Formalizer) Identifiers() *value.ScopeValue {
419	return this.identifiers
420}
421
422func (this *Formalizer) Aliases() *value.ScopeValue {
423	return this.aliases
424}
425
426// Argument must be non-nil
427func (this *Formalizer) SetIdentifiers(identifiers *value.ScopeValue) {
428	this.identifiers = identifiers
429}
430
431func (this *Formalizer) SetAlias(alias string) {
432	if alias != "" {
433		// we treat alias for keyspace as well as equivalent such as
434		// subquery term, expression term, as same to keyspace
435		var ident_flags uint32 = IDENT_IS_KEYSPACE
436		this.aliases.SetField(alias, value.NewValue(ident_flags))
437	}
438}
439
440// alias must be non-empty
441func (this *Formalizer) SetAllowedAlias(alias string, isKeyspace bool) {
442	var ident_flags uint32
443	if isKeyspace {
444		ident_flags = IDENT_IS_KEYSPACE
445	} else {
446		ident_flags = IDENT_IS_UNKNOWN
447	}
448	this.allowed.SetField(alias, value.NewValue(ident_flags))
449}
450
451// alias must be non-empty
452func (this *Formalizer) SetAllowedUnnestAlias(alias string) {
453	ident_flags := uint32(IDENT_IS_KEYSPACE | IDENT_IS_UNNEST_ALIAS)
454	this.allowed.SetField(alias, value.NewValue(ident_flags))
455}
456