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 algebra
11
12import (
13	"encoding/json"
14
15	"github.com/couchbase/query/auth"
16	"github.com/couchbase/query/datastore"
17	"github.com/couchbase/query/errors"
18	"github.com/couchbase/query/expression"
19	"github.com/couchbase/query/value"
20)
21
22/*
23Represents the create primary index ddl statement.
24Indexes always use case-insensitive matching to
25match field names and paths. Index names are unique
26per bucket. Type CreatePrimaryIndex is a struct that
27contains fields keyspaceref and the using IndexType
28string.
29*/
30type CreatePrimaryIndex struct {
31	statementBase
32
33	name      string              `json:"name"`
34	keyspace  *KeyspaceRef        `json:"keyspace"`
35	partition *IndexPartitionTerm `json:"partition"`
36	using     datastore.IndexType `json:"using"`
37	with      value.Value         `json:"with"`
38}
39
40/*
41The function NewCreatePrimaryIndex returns a pointer
42to the CreatePrimaryIndex struct with the input
43argument values as fields.
44*/
45func NewCreatePrimaryIndex(name string, keyspace *KeyspaceRef, partition *IndexPartitionTerm,
46	using datastore.IndexType, with value.Value) *CreatePrimaryIndex {
47	rv := &CreatePrimaryIndex{
48		name:      name,
49		keyspace:  keyspace,
50		partition: partition,
51		using:     using,
52		with:      with,
53	}
54
55	rv.stmt = rv
56	return rv
57}
58
59/*
60It calls the VisitCreatePrimaryIndex method by passing
61in the receiver and returns the interface. It is a
62visitor pattern.
63*/
64func (this *CreatePrimaryIndex) Accept(visitor Visitor) (interface{}, error) {
65	return visitor.VisitCreatePrimaryIndex(this)
66}
67
68/*
69Returns nil.
70*/
71func (this *CreatePrimaryIndex) Signature() value.Value {
72	return nil
73}
74
75/*
76Returns nil.
77*/
78func (this *CreatePrimaryIndex) Formalize() error {
79	f := expression.NewKeyspaceFormalizer(this.keyspace.Keyspace(), nil)
80	return this.MapExpressions(f)
81}
82
83/*
84Returns nil.
85*/
86func (this *CreatePrimaryIndex) MapExpressions(mapper expression.Mapper) (err error) {
87	if this.partition != nil {
88		err = this.partition.MapExpressions(mapper)
89		if err != nil {
90			return
91		}
92	}
93	return
94}
95
96/*
97Returns all contained Expressions.
98*/
99func (this *CreatePrimaryIndex) Expressions() expression.Expressions {
100	if this.partition != nil && len(this.partition.Expressions()) > 0 {
101		return this.partition.Expressions()
102	}
103
104	return nil
105}
106
107/*
108Returns all required privileges.
109*/
110func (this *CreatePrimaryIndex) Privileges() (*auth.Privileges, errors.Error) {
111	privs := auth.NewPrivileges()
112	privs.Add(this.keyspace.Namespace()+":"+this.keyspace.Keyspace(), auth.PRIV_QUERY_CREATE_INDEX)
113
114	for _, expr := range this.Expressions() {
115		privs.AddAll(expr.Privileges())
116	}
117
118	return privs, nil
119}
120
121/*
122Index name.
123*/
124func (this *CreatePrimaryIndex) Name() string {
125	return this.name
126}
127
128/*
129Returns the input keyspace.
130*/
131func (this *CreatePrimaryIndex) Keyspace() *KeyspaceRef {
132	return this.keyspace
133}
134
135/*
136Returns the Partition expression of the create index statement.
137*/
138func (this *CreatePrimaryIndex) Partition() *IndexPartitionTerm {
139	return this.partition
140}
141
142/*
143Returns the index type string for the using clause.
144*/
145func (this *CreatePrimaryIndex) Using() datastore.IndexType {
146	return this.using
147}
148
149/*
150Returns the WITH deployment plan.
151*/
152func (this *CreatePrimaryIndex) With() value.Value {
153	return this.with
154}
155
156/*
157Marshals input receiver into byte array.
158*/
159func (this *CreatePrimaryIndex) MarshalJSON() ([]byte, error) {
160	r := map[string]interface{}{"type": "createPrimaryIndex"}
161	r["name"] = this.name
162	r["keyspaceRef"] = this.keyspace
163	r["using"] = this.using
164	if this.partition != nil {
165		r["partition"] = this.partition
166	}
167	if this.with != nil {
168		r["with"] = this.with
169	}
170
171	return json.Marshal(r)
172}
173
174func (this *CreatePrimaryIndex) Type() string {
175	return "CREATE_PRIMARY_INDEX"
176}
177