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.select;
22  
23  import org.apache.expreval.client.InternalErrorException;
24  import org.apache.expreval.expr.var.NamedParameter;
25  import org.apache.hadoop.hbase.client.Result;
26  import org.apache.hadoop.hbase.hbql.client.HBqlException;
27  import org.apache.hadoop.hbase.hbql.client.HConnection;
28  import org.apache.hadoop.hbase.hbql.impl.AggregateValue;
29  import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
30  import org.apache.hadoop.hbase.hbql.impl.HRecordImpl;
31  import org.apache.hadoop.hbase.hbql.io.IO;
32  import org.apache.hadoop.hbase.hbql.mapping.ColumnAttrib;
33  import org.apache.hadoop.hbase.hbql.mapping.MappingContext;
34  import org.apache.hadoop.hbase.hbql.mapping.ResultAccessor;
35  import org.apache.hadoop.hbase.hbql.mapping.SelectFamilyAttrib;
36  import org.apache.hadoop.hbase.hbql.mapping.TableMapping;
37  import org.apache.hadoop.hbase.hbql.statement.SelectStatement;
38  import org.apache.hadoop.hbase.hbql.util.Lists;
39  
40  import java.util.Collection;
41  import java.util.List;
42  import java.util.NavigableMap;
43  
44  public class FamilySelectElement implements SelectElement {
45  
46      private final List<String> familyNameList = Lists.newArrayList();
47      private final List<byte[]> familyNameBytesList = Lists.newArrayList();
48      private final List<ColumnAttrib> attribsUsedInExpr = Lists.newArrayList();
49      private final String familyName;
50      private final boolean useAllFamilies;
51  
52      private MappingContext mappingContext;
53  
54      public FamilySelectElement(final String familyName) {
55  
56          this.familyName = familyName;
57  
58          if (familyName.equals("*")) {
59              this.useAllFamilies = true;
60          }
61          else {
62              this.useAllFamilies = false;
63              this.addAFamily(familyName.replaceAll(" ", "").replace(":*", ""));
64          }
65      }
66  
67      public void addAFamily(final String familyName) {
68          this.familyNameList.add(familyName);
69      }
70  
71      public static List<SelectElement> newAllFamilies() {
72          final List<SelectElement> retval = Lists.newArrayList();
73          retval.add(new FamilySelectElement("*"));
74          return retval;
75      }
76  
77      public static FamilySelectElement newFamilyElement(final String family) {
78          return new FamilySelectElement(family);
79      }
80  
81      public List<String> getFamilyNameList() {
82          return this.familyNameList;
83      }
84  
85      public List<byte[]> getFamilyNameBytesList() {
86          return this.familyNameBytesList;
87      }
88  
89      private MappingContext getMappingContext() {
90          return this.mappingContext;
91      }
92  
93      protected TableMapping getTableMapping() throws HBqlException {
94          return this.getMappingContext().getTableMapping();
95      }
96  
97      private ResultAccessor getResultAccessor() throws HBqlException {
98          return this.getMappingContext().getResultAccessor();
99      }
100 
101     private void setMappingContext(final MappingContext mappingContext) {
102         this.mappingContext = mappingContext;
103     }
104 
105     public String getAsName() {
106         return null;
107     }
108 
109     public String getElementName() {
110         return null;
111     }
112 
113     public boolean hasAsName() {
114         return false;
115     }
116 
117     public boolean isAFamilySelect() {
118         return true;
119     }
120 
121     public String asString() {
122         return this.familyName;
123     }
124 
125     public boolean isAnAggregateElement() {
126         return false;
127     }
128 
129     public List<NamedParameter> getParameterList() {
130         return null;
131     }
132 
133     public void reset() {
134         // Do nothing
135     }
136 
137     public int setParameter(final String name, final Object val) {
138         // Do nothing
139         return 0;
140     }
141 
142     public void validate(final MappingContext mappingContext, final HConnection connection) throws HBqlException {
143 
144         this.setMappingContext(mappingContext);
145 
146         this.getAttribsUsedInExpr().clear();
147         final Collection<String> familyList = this.getTableMapping().getMappingFamilyNames();
148 
149         if (this.useAllFamilies) {
150             // connction will be null from tests
151             for (final String familyName : familyList) {
152                 this.addAFamily(familyName);
153                 this.attribsUsedInExpr.add(new SelectFamilyAttrib(familyName));
154             }
155         }
156         else {
157             // Only has one family
158             final String familyName = this.getFamilyNameList().get(0);
159             if (!familyList.contains(familyName))
160                 throw new HBqlException("Invalid family name: " + familyName);
161 
162             this.getAttribsUsedInExpr().add(new SelectFamilyAttrib(familyName));
163         }
164 
165         for (final String familyName : this.getFamilyNameList())
166             this.getFamilyNameBytesList().add(IO.getSerialization().getStringAsBytes(familyName));
167     }
168 
169 
170     public List<ColumnAttrib> getAttribsUsedInExpr() {
171         return this.attribsUsedInExpr;
172     }
173 
174     public void assignAsNamesForExpressions(final SelectStatement selectStatement) {
175         // No op
176     }
177 
178     public AggregateValue newAggregateValue() throws HBqlException {
179         throw new InternalErrorException();
180     }
181 
182     public void validateTypes(final boolean allowColumns, final boolean allowCollections) throws HBqlException {
183         // No op;
184     }
185 
186     public void assignSelectValue(final HConnectionImpl conn,
187                                   final Object obj,
188                                   final int maxVersions,
189                                   final Result result) throws HBqlException {
190 
191         final TableMapping tableMapping = this.getTableMapping();
192 
193         // Evaluate each of the families (select * will yield all families)
194         for (int i = 0; i < this.getFamilyNameBytesList().size(); i++) {
195 
196             final String familyName = this.getFamilyNameList().get(i);
197             final byte[] familyNameBytes = this.getFamilyNameBytesList().get(i);
198 
199             final NavigableMap<byte[], byte[]> columnMap = result.getFamilyMap(familyNameBytes);
200 
201             for (final byte[] columnBytes : columnMap.keySet()) {
202 
203                 final byte[] valueBytes = columnMap.get(columnBytes);
204                 final String columnName = IO.getSerialization().getStringFromBytes(columnBytes);
205 
206                 if (obj instanceof HRecordImpl) {
207                     final HRecordImpl record = (HRecordImpl)obj;
208                     record.addNameToPositionList(familyName + ":" + columnName);
209                 }
210 
211                 final ColumnAttrib attrib = this.getResultAccessor().getColumnAttribByQualifiedName(familyName,
212                                                                                                     columnName);
213                 if (attrib == null) {
214                     final ColumnAttrib unMappedAttrib = tableMapping.getUnMappedAttrib(familyName);
215                     if (unMappedAttrib != null)
216                         unMappedAttrib.setUnMappedCurrentValue(obj, columnName, valueBytes);
217                 }
218                 else {
219                     attrib.setCurrentValue(obj, 0, valueBytes);
220                 }
221             }
222 
223             // Bail if no versions were requested
224             if (maxVersions <= 1)
225                 continue;
226 
227             final NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> familyMap = result.getMap();
228             final NavigableMap<byte[], NavigableMap<Long, byte[]>> versionColumnMap = familyMap.get(familyNameBytes);
229 
230             if (versionColumnMap == null)
231                 continue;
232 
233             for (final byte[] columnBytes : versionColumnMap.keySet()) {
234 
235                 final NavigableMap<Long, byte[]> timeStampMap = versionColumnMap.get(columnBytes);
236                 final String columnName = IO.getSerialization().getStringFromBytes(columnBytes);
237 
238                 final ColumnAttrib attrib = this.getResultAccessor().getVersionAttrib(familyName, columnName);
239 
240                 if (attrib == null) {
241                     final ColumnAttrib unMappedAttrib = tableMapping.getUnMappedAttrib(familyName);
242                     if (unMappedAttrib != null)
243                         unMappedAttrib.setUnMappedVersionMap(obj, columnName, timeStampMap);
244                 }
245                 else {
246                     attrib.setVersionMap(obj, timeStampMap);
247                 }
248             }
249         }
250     }
251 }