1 using System.Collections.Generic;
2 using System.Text.RegularExpressions;
16 private enum ColumnType
46 private struct DecimalInfo
55 private static readonly Regex DECIMAL_REGEX =
new Regex(
@"decimal\s*\(\s*(\d+)\s*,\s*(\d+)\s*\)", RegexOptions.IgnoreCase);
60 private IList<int> routing_column_indices;
61 private IList<ColumnType> column_types;
62 private IDictionary<int, DecimalInfo> decimal_infos;
63 private int buffer_size;
70 routing_column_indices =
new List<int>();
71 column_types =
new List<ColumnType>();
72 decimal_infos =
new Dictionary<int, DecimalInfo>();
77 bool has_timestamp =
false;
80 int track_id_column_idx = -1;
85 for (
int i = 0; i < columns.Count; ++i)
91 switch (column.getName())
94 track_id_column_idx = i;
114 routing_column_indices.Add(i);
118 routing_column_indices.Add(i);
124 && has_timestamp && has_x && has_y && (track_id_column_idx != -1))
126 if (routing_column_indices.Count == 0)
128 routing_column_indices.Add(track_id_column_idx);
130 else if ((routing_column_indices.Count != 1)
131 || (routing_column_indices[0] != track_id_column_idx))
134 throw new KineticaException(
"Cannot have a shard key other than 'TRACKID' for track tables.");
141 foreach (
int i
in routing_column_indices)
146 switch (column.getType())
151 column_types.Add(ColumnType.FLOAT);
152 this.buffer_size += 4;
157 column_types.Add(ColumnType.DOUBLE);
158 this.buffer_size += 8;
167 column_types.Add(ColumnType.INT8);
168 this.buffer_size += 1;
172 column_types.Add(ColumnType.INT16);
173 this.buffer_size += 2;
177 column_types.Add(ColumnType.INT);
178 this.buffer_size += 4;
188 column_types.Add(ColumnType.TIMESTAMP);
192 column_types.Add(ColumnType.LONG);
194 this.buffer_size += 8;
202 column_types.Add(ColumnType.CHAR1);
203 this.buffer_size += 1;
207 column_types.Add(ColumnType.CHAR2);
208 this.buffer_size += 2;
212 column_types.Add(ColumnType.CHAR4);
213 this.buffer_size += 4;
217 column_types.Add(ColumnType.CHAR8);
218 this.buffer_size += 8;
222 column_types.Add(ColumnType.CHAR16);
223 this.buffer_size += 16;
227 column_types.Add(ColumnType.CHAR32);
228 this.buffer_size += 32;
232 column_types.Add(ColumnType.CHAR64);
233 this.buffer_size += 64;
237 column_types.Add(ColumnType.CHAR128);
238 this.buffer_size += 128;
242 column_types.Add(ColumnType.CHAR256);
243 this.buffer_size += 256;
247 column_types.Add(ColumnType.DATE);
248 this.buffer_size += 4;
252 column_types.Add(ColumnType.DATETIME);
253 this.buffer_size += 8;
255 else if (HasDecimalProperty(column.getProperties(), out
int precision, out
int scale))
258 decimal_infos[i] =
new DecimalInfo { Precision = precision, Scale = scale };
263 column_types.Add(ColumnType.DECIMAL_BIG);
264 this.buffer_size += 12;
268 column_types.Add(ColumnType.DECIMAL);
269 this.buffer_size += 8;
274 column_types.Add(ColumnType.IPV4);
275 this.buffer_size += 4;
279 column_types.Add(ColumnType.TIME);
280 this.buffer_size += 4;
284 column_types.Add(ColumnType.STRING);
285 this.buffer_size += 8;
293 throw new KineticaException($
"Cannot use column '{column.getName()}' as a key.");
307 private static bool HasDecimalProperty(IList<string> properties, out
int precision, out
int scale)
311 bool foundDecimal =
false;
313 foreach (var prop
in properties)
323 var match = DECIMAL_REGEX.Match(prop);
327 if (
int.TryParse(match.Groups[1].Value, out
int p))
329 if (
int.TryParse(match.Groups[2].Value, out
int s))
335 if (prop.StartsWith(
"precision=", System.StringComparison.OrdinalIgnoreCase))
337 var val = prop.Substring(10);
338 if (
int.TryParse(val, out
int p))
345 if (prop.StartsWith(
"scale=", System.StringComparison.OrdinalIgnoreCase))
347 var val = prop.Substring(6);
348 if (
int.TryParse(val, out
int s))
369 if (this.buffer_size == 0)
376 for (
int i = 0; i < this.routing_column_indices.Count; ++i)
382 var value = record.GetType().GetProperty(column.getName()).GetValue(record,
null);
384 switch (this.column_types[i])
386 case ColumnType.CHAR1:
390 case ColumnType.CHAR2:
394 case ColumnType.CHAR4:
398 case ColumnType.CHAR8:
402 case ColumnType.CHAR16:
406 case ColumnType.CHAR32:
410 case ColumnType.CHAR64:
414 case ColumnType.CHAR128:
418 case ColumnType.CHAR256:
422 case ColumnType.DATE:
426 case ColumnType.DATETIME:
430 case ColumnType.DECIMAL:
433 var decInfo = decimal_infos.TryGetValue(this.routing_column_indices[i], out var info)
435 :
new DecimalInfo { Precision = 19, Scale = 4 };
436 key.
addDecimal((
string)value, decInfo.Precision, decInfo.Scale);
440 case ColumnType.DECIMAL_BIG:
443 var decInfo = decimal_infos.TryGetValue(this.routing_column_indices[i], out var info)
445 :
new DecimalInfo { Precision = 38, Scale = 10 };
446 key.
addDecimal((
string)value, decInfo.Precision, decInfo.Scale);
450 case ColumnType.DOUBLE:
454 case ColumnType.FLOAT:
462 case ColumnType.INT8:
466 case ColumnType.INT16:
470 case ColumnType.IPV4:
474 case ColumnType.LONG:
478 case ColumnType.STRING:
482 case ColumnType.TIME:
486 case ColumnType.TIMESTAMP:
511 if (this.buffer_size == 0)
515 System.Text.StringBuilder expression =
new System.Text.StringBuilder(
"(" );
518 for (
int i = 0; i < this.routing_column_indices.Count; ++i)
521 expression.Append(
" and " );
525 string column_name = column.getName();
528 var value = record.GetType().GetProperty( column_name ).GetValue( record,
null );
533 expression.Append(
"is_null(" );
534 expression.Append( column_name );
535 expression.Append(
")" );
540 expression.Append(
"(" );
541 expression.Append( column_name );
542 expression.Append(
" = " );
545 switch ( this.column_types[i] )
548 case ColumnType.CHAR1:
549 case ColumnType.CHAR2:
550 case ColumnType.CHAR4:
551 case ColumnType.CHAR8:
552 case ColumnType.CHAR16:
553 case ColumnType.CHAR32:
554 case ColumnType.CHAR64:
555 case ColumnType.CHAR128:
556 case ColumnType.CHAR256:
557 case ColumnType.DATE:
558 case ColumnType.DATETIME:
559 case ColumnType.DECIMAL:
560 case ColumnType.DECIMAL_BIG:
561 case ColumnType.IPV4:
562 case ColumnType.STRING:
563 case ColumnType.TIME:
564 expression.Append(
"\"" );
565 expression.Append( value );
566 expression.Append(
"\"" );
569 case ColumnType.DOUBLE:
570 case ColumnType.FLOAT:
572 case ColumnType.INT8:
573 case ColumnType.INT16:
574 case ColumnType.LONG:
575 expression.Append( value );
580 expression.Append(
")" );
584 expression.Append(
")" );
586 return expression.ToString();
599 return !(this.routing_column_indices.Count == 0);
610 return this.column_types.Equals(other.column_types);
const string CHAR64
This property provides optimized memory, disk and query performance for string columns.
const string INT16
This property provides optimized memory and query performance for int columns.
void addCharN(string value, int N)
Appends a charN value to the buffer.
void addInt8(int? value)
Add an 8-bit integer to the buffer.
const string CHAR128
This property provides optimized memory, disk and query performance for string columns.
const string SHARD_KEY
This property indicates that this column will be part of (or the entire) shard key.
void addInt16(int? value)
Add a short (two bytes) to the buffer.
void addDecimal(string value, int precision, int scale)
Adds a decimal value to the buffer with specified precision and scale.
const string CHAR1
This property provides optimized memory, disk and query performance for string columns.
void addDate(string value)
Adds a string to the buffer that has the 'date' property.
void addInt(int? value)
Add an integer to the buffer.
A binary key used for shard routing.
const string TIMESTAMP
Valid only for 'long' columns.
RecordKeyBuilder(bool is_primary_key, KineticaType ktype)
void computeHashes()
Compute the hash of the key in the buffer.
bool hasKey()
Returns whether this builder builds any routing keys.
const string TIME
Valid only for 'string' columns.
const string DECIMAL
Valid only for 'string' columns.
const string IPV4
This property provides optimized memory, disk and query performance for string columns representing I...
const string CHAR2
This property provides optimized memory, disk and query performance for string columns.
void addTime(string value)
Adds a string to the buffer that has the 'time' property.
const string CHAR8
This property provides optimized memory, disk and query performance for string columns.
const string CHAR32
This property provides optimized memory, disk and query performance for string columns.
const string CHAR256
This property provides optimized memory, disk and query performance for string columns.
const string PRIMARY_KEY
This property indicates that this column will be part of (or the entire) primary key.
RecordKey build(T record)
Build a RecordKey object based on a record.
Column properties used for Kinetica types.
void addString(string value)
Add a string to the buffer.
bool hasSameKey(RecordKeyBuilder< T > other)
Returns if other is equivalent to this builder.
IList< Column > getColumns()
void addIPv4(string value)
Adds a string to the buffer that has the 'ipv4' property.
const string DATETIME
Valid only for 'string' columns.
void addTimeStamp(long? value)
Adds a long to the buffer that has the 'timestamp' property.
void addLong(long? value)
Add a long to the buffer.
void addDouble(double? value)
Add a double to the buffer.
void addDateTime(string value)
Adds a string to the buffer that has the 'datetime' property.
const string INT8
This property provides optimized memory and query performance for int columns.
const string CHAR16
This property provides optimized memory, disk and query performance for string columns.
string buildExpression(T record)
Build an expression to be passed to getRecords in the option.
Builds or creates RecordKey objects based on a given record.
void addFloat(float? value)
Add a float to the buffer.
const string CHAR4
This property provides optimized memory, disk and query performance for string columns.
const string DATE
Valid only for 'string' columns.