1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.protobuf.ByteString;
27 import com.pingcap.tidb.tipb.ColumnInfo;
28 import java.io.Serializable;
29 import java.util.List;
30 import java.util.Objects;
31 import org.tikv.common.codec.CodecDataOutput;
32 import org.tikv.common.types.DataType;
33 import org.tikv.common.types.DataType.EncodeType;
34 import org.tikv.common.types.DataTypeFactory;
35 import org.tikv.common.types.IntegerType;
36 import org.tikv.common.types.MySQLType;
37
38 @JsonIgnoreProperties(ignoreUnknown = true)
39 public class TiColumnInfo implements Serializable {
40 @VisibleForTesting private static final int PK_MASK = 0x2;
41 private final long id;
42 private final String name;
43 private final int offset;
44 private final DataType type;
45 private final org.tikv.common.meta.SchemaState schemaState;
46 private final String comment;
47 private final boolean isPrimaryKey;
48 private final String defaultValue;
49 private final String originDefaultValue;
50 private final String defaultValueBit;
51
52
53
54 private final long version;
55 private final String generatedExprString;
56
57 @JsonCreator
58 public TiColumnInfo(
59 @JsonProperty("id") long id,
60 @JsonProperty("name") org.tikv.common.meta.CIStr name,
61 @JsonProperty("offset") int offset,
62 @JsonProperty("type") InternalTypeHolder type,
63 @JsonProperty("state") int schemaState,
64 @JsonProperty("origin_default") String originalDefaultValue,
65 @JsonProperty("default") String defaultValue,
66 @JsonProperty("default_bit") String defaultValueBit,
67 @JsonProperty("comment") String comment,
68 @JsonProperty("version") long version,
69 @JsonProperty("generated_expr_string") String generatedExprString) {
70 this.id = id;
71 this.name = requireNonNull(name, "column name is null").getL();
72 this.offset = offset;
73 this.type = DataTypeFactory.of(requireNonNull(type, "type is null"));
74 this.schemaState = org.tikv.common.meta.SchemaState.fromValue(schemaState);
75 this.comment = comment;
76 this.defaultValue = defaultValue;
77 this.originDefaultValue = originalDefaultValue;
78 this.defaultValueBit = defaultValueBit;
79
80
81 this.isPrimaryKey = (type.getFlag() & PK_MASK) > 0;
82 this.version = version;
83 this.generatedExprString = generatedExprString;
84 }
85
86 public TiColumnInfo(
87 long id,
88 String name,
89 int offset,
90 DataType type,
91 org.tikv.common.meta.SchemaState schemaState,
92 String originalDefaultValue,
93 String defaultValue,
94 String defaultValueBit,
95 String comment,
96 long version,
97 String generatedExprString) {
98 this.id = id;
99 this.name = requireNonNull(name, "column name is null").toLowerCase();
100 this.offset = offset;
101 this.type = requireNonNull(type, "data type is null");
102 this.schemaState = schemaState;
103 this.comment = comment;
104 this.defaultValue = defaultValue;
105 this.originDefaultValue = originalDefaultValue;
106 this.defaultValueBit = defaultValueBit;
107 this.isPrimaryKey = (type.getFlag() & PK_MASK) > 0;
108 this.version = version;
109 this.generatedExprString = generatedExprString;
110 }
111
112 @VisibleForTesting
113 public TiColumnInfo(long id, String name, int offset, DataType type, boolean isPrimaryKey) {
114 this.id = id;
115 this.name = requireNonNull(name, "column name is null").toLowerCase();
116 this.offset = offset;
117 this.type = requireNonNull(type, "data type is null");
118 this.schemaState = org.tikv.common.meta.SchemaState.StatePublic;
119 this.comment = "";
120 this.isPrimaryKey = isPrimaryKey;
121 this.originDefaultValue = "1";
122 this.defaultValue = "";
123 this.defaultValueBit = null;
124 this.version = DataType.COLUMN_VERSION_FLAG;
125 this.generatedExprString = "";
126 }
127
128 static TiColumnInfo getRowIdColumn(int offset) {
129 return new TiColumnInfo(-1, "_tidb_rowid", offset, IntegerType.ROW_ID_TYPE, true);
130 }
131
132 TiColumnInfo copyWithoutPrimaryKey() {
133 InternalTypeHolder typeHolder = type.toTypeHolder();
134 typeHolder.setFlag(type.getFlag() & (~TiColumnInfo.PK_MASK));
135 DataType newType = DataTypeFactory.of(typeHolder);
136 return new TiColumnInfo(
137 this.id,
138 this.name,
139 this.offset,
140 newType,
141 this.schemaState,
142 this.originDefaultValue,
143 this.defaultValue,
144 this.defaultValueBit,
145 this.comment,
146 this.version,
147 this.generatedExprString);
148 }
149
150 public long getId() {
151 return this.id;
152 }
153
154 public String getName() {
155 return this.name;
156 }
157
158 public boolean matchName(String name) {
159 return this.name.equalsIgnoreCase(name)
160 || String.format("`%s`", this.name).equalsIgnoreCase(name);
161 }
162
163 public int getOffset() {
164 return this.offset;
165 }
166
167 public DataType getType() {
168 return type;
169 }
170
171 public long getLength() {
172 return getType().getLength();
173 }
174
175 public long getSize() {
176 return getType().getSize();
177 }
178
179 org.tikv.common.meta.SchemaState getSchemaState() {
180 return schemaState;
181 }
182
183 public String getComment() {
184 return comment;
185 }
186
187 public boolean isPrimaryKey() {
188 return isPrimaryKey;
189 }
190
191 String getDefaultValue() {
192 return defaultValue;
193 }
194
195 public String getDefaultValueBit() {
196 return defaultValueBit;
197 }
198
199
200
201 String getOriginDefaultValue() {
202 if (this.getType().getType() == MySQLType.TypeBit
203 && originDefaultValue != null
204 && defaultValueBit != null) {
205 return defaultValueBit;
206 } else {
207 return originDefaultValue;
208 }
209 }
210
211 private ByteString getOriginDefaultValueAsByteString() {
212 CodecDataOutput cdo = new CodecDataOutput();
213 type.encode(
214 cdo, EncodeType.VALUE, type.getOriginDefaultValue(getOriginDefaultValue(), version));
215 return cdo.toByteString();
216 }
217
218 public long getVersion() {
219 return version;
220 }
221
222 public boolean isAutoIncrement() {
223 return this.type.isAutoIncrement();
224 }
225
226 TiIndexColumn toFakeIndexColumn() {
227
228
229 return new TiIndexColumn(
230 org.tikv.common.meta.CIStr.newCIStr(getName()), getOffset(), DataType.UNSPECIFIED_LEN);
231 }
232
233 TiIndexColumn toIndexColumn() {
234 return new TiIndexColumn(
235 org.tikv.common.meta.CIStr.newCIStr(getName()), getOffset(), getType().getLength());
236 }
237
238 ColumnInfo toProto(TiTableInfo tableInfo) {
239 return ColumnInfo.newBuilder()
240 .setColumnId(id)
241 .setTp(type.getTypeCode())
242 .setCollation(type.getCollationCode())
243 .setColumnLen((int) type.getLength())
244 .setDecimal(type.getDecimal())
245 .setFlag(type.getFlag())
246 .setDefaultVal(getOriginDefaultValueAsByteString())
247 .setPkHandle(tableInfo.isPkHandle() && isPrimaryKey())
248 .addAllElems(type.getElems())
249 .build();
250 }
251
252 @Override
253 public boolean equals(Object other) {
254 if (other == this) {
255 return true;
256 }
257
258 if (!(other instanceof TiColumnInfo)) {
259 return false;
260 }
261
262 TiColumnInfo col = (TiColumnInfo) other;
263 return Objects.equals(id, col.id)
264 && Objects.equals(name, col.name)
265 && Objects.equals(type, col.type)
266 && Objects.equals(schemaState, col.schemaState)
267 && isPrimaryKey == col.isPrimaryKey
268 && Objects.equals(defaultValue, col.defaultValue)
269 && Objects.equals(originDefaultValue, col.originDefaultValue);
270 }
271
272 @Override
273 public int hashCode() {
274 return Objects.hash(
275 id, name, type, schemaState, isPrimaryKey, defaultValue, originDefaultValue);
276 }
277
278 public String getGeneratedExprString() {
279 return generatedExprString;
280 }
281
282 public boolean isGeneratedColumn() {
283 return generatedExprString != null && !generatedExprString.isEmpty();
284 }
285
286 @JsonIgnoreProperties(ignoreUnknown = true)
287 public static class InternalTypeHolder {
288 private int tp;
289 private int flag;
290 private long flen;
291 private int decimal;
292 private String charset;
293 private String collate;
294 private List<String> elems;
295
296 @JsonCreator
297 public InternalTypeHolder(
298 @JsonProperty("Tp") int tp,
299 @JsonProperty("Flag") int flag,
300 @JsonProperty("Flen") long flen,
301 @JsonProperty("Decimal") int decimal,
302 @JsonProperty("Charset") String charset,
303 @JsonProperty("Collate") String collate,
304 @JsonProperty("Elems") List<String> elems) {
305 this.tp = tp;
306 this.flag = flag;
307 this.flen = flen;
308 this.decimal = decimal;
309 this.charset = charset;
310 this.collate = collate;
311 this.elems = elems;
312 }
313
314 public int getTp() {
315 return tp;
316 }
317
318 public void setTp(int tp) {
319 this.tp = tp;
320 }
321
322 public int getFlag() {
323 return flag;
324 }
325
326 public void setFlag(int flag) {
327 this.flag = flag;
328 }
329
330 public long getFlen() {
331 return flen;
332 }
333
334 public void setFlen(long flen) {
335 this.flen = flen;
336 }
337
338 public int getDecimal() {
339 return decimal;
340 }
341
342 public void setDecimal(int decimal) {
343 this.decimal = decimal;
344 }
345
346 public String getCharset() {
347 return charset;
348 }
349
350 public void setCharset(String charset) {
351 this.charset = charset;
352 }
353
354 public String getCollate() {
355 return collate;
356 }
357
358 public void setCollate(String collate) {
359 this.collate = collate;
360 }
361
362 public List<String> getElems() {
363 return elems;
364 }
365
366 public void setElems(List<String> elems) {
367 this.elems = elems;
368 }
369
370 interface Builder<E extends DataType> {
371 E build(InternalTypeHolder holder);
372 }
373 }
374 }