View Javadoc

1   /*
2    * Copyright (c) 2010.  The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.hbql.statement;
22  
23  import org.apache.hadoop.hbase.client.tableindexed.IndexSpecification;
24  import org.apache.hadoop.hbase.hbql.client.ExecutionResults;
25  import org.apache.hadoop.hbase.hbql.client.HBqlException;
26  import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
27  import org.apache.hadoop.hbase.hbql.index.SingleColumnIndex;
28  import org.apache.hadoop.hbase.hbql.mapping.ColumnAttrib;
29  import org.apache.hadoop.hbase.hbql.mapping.TableMapping;
30  import org.apache.hadoop.hbase.hbql.util.Lists;
31  
32  import java.io.IOException;
33  import java.util.List;
34  
35  public class CreateIndexStatement extends StatementWithMapping implements ConnectionStatement {
36  
37      private final String indexName;
38      private final List<String> indexColumns;
39      private final List<String> includeColumns;
40  
41      public CreateIndexStatement(final StatementPredicate predicate,
42                                  final String indexName,
43                                  final String mappingName,
44                                  final List<String> indexColumns,
45                                  final List<String> includeColumns) {
46          super(predicate, mappingName);
47          this.indexName = indexName;
48          this.indexColumns = indexColumns;
49          this.includeColumns = includeColumns;
50      }
51  
52      private String getIndexName() {
53          return this.indexName;
54      }
55  
56      protected ExecutionResults execute(final HConnectionImpl conn) throws HBqlException {
57  
58          final TableMapping mapping = conn.getMapping(this.getMappingContext().getMappingName());
59  
60          final List<String> indexList = this.getQualifiedNameList(mapping, this.indexColumns);
61          final List<String> includeList = this.getQualifiedNameList(mapping, this.includeColumns);
62          final IndexSpecification spec = SingleColumnIndex.newIndex(this.getIndexName(), indexList, includeList);
63  
64          try {
65              conn.getIndexTableAdmin().addIndex(mapping.getTableNameAsBytes(), spec);
66          }
67          catch (IOException e) {
68              throw new HBqlException(e);
69          }
70  
71          return new ExecutionResults(this.getCreateIndexMsg(indexList, includeList));
72      }
73  
74      private List<String> getQualifiedNameList(final TableMapping mapping,
75                                                final List<String> columnList) throws HBqlException {
76  
77          final List<String> retval;
78  
79          if (columnList == null) {
80              retval = null;
81          }
82          else {
83  
84              retval = Lists.newArrayList();
85  
86              for (final String column : columnList) {
87                  if (column.endsWith(":*")) {
88                      final String familyName = column.substring(0, column.length() - 2);
89                      retval.add(familyName);
90                  }
91                  else {
92                      final ColumnAttrib columnAttrib = mapping.getAttribByVariableName(column);
93                      if (columnAttrib == null)
94                          throw new HBqlException("Unknown " +
95                                                  ((!column.contains(":")) ? "alias" : "column")
96                                                  + " " + column + " in mapping " + this.getMappingContext()
97                                  .getMappingName());
98                      else
99                          retval.add(columnAttrib.getFamilyQualifiedName());
100                 }
101             }
102         }
103 
104         return retval;
105     }
106 
107     private String getCreateIndexMsg(final List<String> indexList, final List<String> includeList) {
108 
109         final StringBuilder sbuf = new StringBuilder("Index " + this.getIndexName()
110                                                      + " created for " + this.getMappingContext().getMappingName());
111 
112         sbuf.append(" (");
113 
114         boolean first = true;
115         for (final String val : indexList) {
116             if (!first)
117                 sbuf.append(", ");
118             else
119                 first = false;
120 
121             sbuf.append(val);
122         }
123 
124         sbuf.append(")");
125 
126         if (includeList != null) {
127             sbuf.append(" INCLUDE (");
128             first = true;
129             for (final String val : includeList) {
130                 if (!first)
131                     sbuf.append(", ");
132                 else
133                     first = false;
134 
135                 sbuf.append(val);
136             }
137             sbuf.append(")");
138         }
139 
140         return sbuf.toString();
141     }
142 
143     public static String usage() {
144         return "CREATE INDEX index_name ON [MAPPING] mapping_name (column) INCLUDE (column_list) [IF bool_expr]";
145     }
146 }