View Javadoc
1   /*
2    * Copyright 2021 TiKV Project Authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  
18  package org.tikv.common.key;
19  
20  import com.google.common.base.Joiner;
21  import java.util.List;
22  import org.tikv.common.codec.Codec.IntegerCodec;
23  import org.tikv.common.codec.CodecDataOutput;
24  import org.tikv.common.exception.TypeException;
25  import org.tikv.common.meta.TiIndexColumn;
26  import org.tikv.common.meta.TiTableInfo;
27  import org.tikv.common.row.Row;
28  import org.tikv.common.types.DataType;
29  import org.tikv.common.types.IntegerType;
30  
31  public class IndexKey extends Key {
32    private static final byte[] IDX_PREFIX_SEP = new byte[] {'_', 'i'};
33  
34    private final long tableId;
35    private final long indexId;
36    private final Key[] dataKeys;
37  
38    private IndexKey(long tableId, long indexId, Key[] dataKeys) {
39      super(encode(tableId, indexId, dataKeys));
40      this.tableId = tableId;
41      this.indexId = indexId;
42      this.dataKeys = dataKeys;
43    }
44  
45    public static class EncodeIndexDataResult {
46      public EncodeIndexDataResult(Key[] keys, boolean appendHandle) {
47        this.keys = keys;
48        this.appendHandle = appendHandle;
49      }
50  
51      public Key[] keys;
52      public boolean appendHandle;
53    }
54  
55    public static IndexKey toIndexKey(long tableId, long indexId, Key... dataKeys) {
56      return new IndexKey(tableId, indexId, dataKeys);
57    }
58  
59    public static EncodeIndexDataResult encodeIndexDataValues(
60        Row row,
61        List<TiIndexColumn> indexColumns,
62        long handle,
63        boolean appendHandleIfContainsNull,
64        TiTableInfo tableInfo) {
65      // when appendHandleIfContainsNull is true, append handle column if any of the index column is
66      // NULL
67      boolean appendHandle = false;
68      if (appendHandleIfContainsNull) {
69        for (TiIndexColumn col : indexColumns) {
70          DataType colTp = tableInfo.getColumn(col.getOffset()).getType();
71          if (row.get(col.getOffset(), colTp) == null) {
72            appendHandle = true;
73            break;
74          }
75        }
76      }
77      Key[] keys = new Key[indexColumns.size() + (appendHandle ? 1 : 0)];
78      for (int i = 0; i < indexColumns.size(); i++) {
79        TiIndexColumn col = indexColumns.get(i);
80        DataType colTp = tableInfo.getColumn(col.getOffset()).getType();
81        // truncate index's if necessary
82        Key key =
83            org.tikv.common.key.TypedKey.toTypedKey(
84                row.get(col.getOffset(), colTp), colTp, (int) col.getLength());
85        keys[i] = key;
86      }
87      if (appendHandle) {
88        Key key = org.tikv.common.key.TypedKey.toTypedKey(handle, IntegerType.BIGINT);
89        keys[keys.length - 1] = key;
90      }
91  
92      return new EncodeIndexDataResult(keys, appendHandle);
93    }
94  
95    private static byte[] encode(long tableId, long indexId, Key[] dataKeys) {
96      CodecDataOutput cdo = new CodecDataOutput();
97      cdo.write(TBL_PREFIX);
98      IntegerCodec.writeLong(cdo, tableId);
99      cdo.write(IDX_PREFIX_SEP);
100     IntegerCodec.writeLong(cdo, indexId);
101     for (Key key : dataKeys) {
102       if (key == null) {
103         throw new TypeException("key cannot be null");
104       }
105       cdo.write(key.getBytes());
106     }
107     return cdo.toBytes();
108   }
109 
110   public long getTableId() {
111     return tableId;
112   }
113 
114   public long getIndexId() {
115     return indexId;
116   }
117 
118   public Key[] getDataKeys() {
119     return dataKeys;
120   }
121 
122   @Override
123   public String toString() {
124     return String.format("[%s]", Joiner.on(",").useForNull("null").join(dataKeys));
125   }
126 }