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.meta;
19  
20  import static java.util.Objects.requireNonNull;
21  
22  import com.fasterxml.jackson.annotation.JsonCreator;
23  import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
24  import com.fasterxml.jackson.annotation.JsonProperty;
25  import com.google.common.annotations.VisibleForTesting;
26  import com.google.common.base.Joiner;
27  import com.google.common.collect.ImmutableList;
28  import com.pingcap.tidb.tipb.ColumnInfo;
29  import com.pingcap.tidb.tipb.IndexInfo;
30  import java.io.Serializable;
31  import java.util.List;
32  import java.util.stream.Collectors;
33  import org.tikv.common.exception.TiKVException;
34  
35  @JsonIgnoreProperties(ignoreUnknown = true)
36  public class TiIndexInfo implements Serializable {
37    private final long id;
38    private final String name;
39    private final String tableName;
40    private final List<TiIndexColumn> indexColumns;
41    private final boolean isUnique;
42    private final boolean isPrimary;
43    private final org.tikv.common.meta.SchemaState schemaState;
44    private final String comment;
45    private final org.tikv.common.meta.IndexType indexType;
46    private final boolean isFakePrimaryKey;
47  
48    // default index column size (TypeFlag + Int64)
49    private long indexColumnSize = 9;
50  
51    @JsonCreator
52    @VisibleForTesting
53    public TiIndexInfo(
54        @JsonProperty("id") long id,
55        @JsonProperty("idx_name") org.tikv.common.meta.CIStr name,
56        @JsonProperty("tbl_name") org.tikv.common.meta.CIStr tableName,
57        @JsonProperty("idx_cols") List<TiIndexColumn> indexColumns,
58        @JsonProperty("is_unique") boolean isUnique,
59        @JsonProperty("is_primary") boolean isPrimary,
60        @JsonProperty("state") int schemaState,
61        @JsonProperty("comment") String comment,
62        @JsonProperty("index_type") int indexType,
63        // This is a fake property and added JsonProperty only to
64        // to bypass Jackson frameworks's check
65        @JsonProperty("___isFakePrimaryKey") boolean isFakePrimaryKey) {
66      this.id = id;
67      this.name = requireNonNull(name, "index name is null").getL();
68      this.tableName = requireNonNull(tableName, "table name is null").getL();
69      this.indexColumns = ImmutableList.copyOf(requireNonNull(indexColumns, "indexColumns is null"));
70      this.isUnique = isUnique;
71      this.isPrimary = isPrimary;
72      this.schemaState = org.tikv.common.meta.SchemaState.fromValue(schemaState);
73      this.comment = comment;
74      this.indexType = org.tikv.common.meta.IndexType.fromValue(indexType);
75      this.isFakePrimaryKey = isFakePrimaryKey;
76    }
77  
78    public static TiIndexInfo generateFakePrimaryKeyIndex(TiTableInfo table) {
79      org.tikv.common.meta.TiColumnInfo pkColumn = table.getPKIsHandleColumn();
80      if (pkColumn != null) {
81        return new TiIndexInfo(
82            -1,
83            org.tikv.common.meta.CIStr.newCIStr("fake_pk_" + table.getId()),
84            org.tikv.common.meta.CIStr.newCIStr(table.getName()),
85            ImmutableList.of(pkColumn.toFakeIndexColumn()),
86            true,
87            true,
88            org.tikv.common.meta.SchemaState.StatePublic.getStateCode(),
89            "Fake Column",
90            org.tikv.common.meta.IndexType.IndexTypeHash.getTypeCode(),
91            true);
92      }
93      return null;
94    }
95  
96    private long calculateIndexColumnSize(
97        TiIndexColumn indexColumn, List<org.tikv.common.meta.TiColumnInfo> columns) {
98      for (org.tikv.common.meta.TiColumnInfo column : columns) {
99        if (column.getName().equalsIgnoreCase(indexColumn.getName())) {
100         return column.getType().getSize();
101       }
102     }
103     throw new TiKVException(
104         String.format(
105             "Index column [%s] not found in table [%s] columns [%s]",
106             indexColumn.getName(), getTableName(), columns));
107   }
108 
109   void calculateIndexSize(List<org.tikv.common.meta.TiColumnInfo> columns) {
110     long ret = 0;
111     for (TiIndexColumn indexColumn : indexColumns) {
112       if (indexColumn.isLengthUnspecified()) {
113         ret += calculateIndexColumnSize(indexColumn, columns);
114       } else {
115         ret += indexColumn.getLength();
116       }
117     }
118     indexColumnSize = ret;
119   }
120 
121   public long getIndexColumnSize() {
122     return this.indexColumnSize;
123   }
124 
125   public long getId() {
126     return id;
127   }
128 
129   public String getName() {
130     return name;
131   }
132 
133   public String getTableName() {
134     return tableName;
135   }
136 
137   public List<TiIndexColumn> getIndexColumns() {
138     return indexColumns;
139   }
140 
141   public boolean isUnique() {
142     return isUnique;
143   }
144 
145   public boolean isPrimary() {
146     return isPrimary;
147   }
148 
149   public org.tikv.common.meta.SchemaState getSchemaState() {
150     return schemaState;
151   }
152 
153   public String getComment() {
154     return comment;
155   }
156 
157   public org.tikv.common.meta.IndexType getIndexType() {
158     return indexType;
159   }
160 
161   public IndexInfo toProto(TiTableInfo tableInfo) {
162     IndexInfo.Builder builder =
163         IndexInfo.newBuilder().setTableId(tableInfo.getId()).setIndexId(id).setUnique(isUnique);
164 
165     List<org.tikv.common.meta.TiColumnInfo> columns = tableInfo.getColumns();
166 
167     for (TiIndexColumn indexColumn : getIndexColumns()) {
168       int offset = indexColumn.getOffset();
169       org.tikv.common.meta.TiColumnInfo column = columns.get(offset);
170       builder.addColumns(column.toProto(tableInfo));
171     }
172 
173     if (tableInfo.isPkHandle()) {
174       for (org.tikv.common.meta.TiColumnInfo column : columns) {
175         if (!column.isPrimaryKey()) {
176           continue;
177         }
178         ColumnInfo pbColumn = column.toProto(tableInfo);
179         builder.addColumns(pbColumn);
180       }
181     }
182     return builder.build();
183   }
184 
185   public boolean isFakePrimaryKey() {
186     return isFakePrimaryKey;
187   }
188 
189   @Override
190   public String toString() {
191     return String.format(
192         "%s[%s]",
193         name,
194         Joiner.on(",")
195             .skipNulls()
196             .join(indexColumns.stream().map(TiIndexColumn::getName).collect(Collectors.toList())));
197   }
198 }