2 using System.Collections.Generic;
3 using System.Runtime.CompilerServices;
5 using System.Text.RegularExpressions;
7 namespace kinetica.Records;
18 private readonly IReadOnlyList<int> _shardKeyIndices;
19 private readonly IReadOnlyList<ColumnType> _shardKeyTypes;
20 private readonly IReadOnlyDictionary<int, (
int Precision,
int Scale)> _decimalInfos;
21 private readonly IReadOnlyDictionary<int, int> _charLengths;
22 private readonly
int _bufferSize;
23 private readonly IReadOnlyDictionary<string, int> _columnNameToShardIndex;
31 throw new ArgumentNullException(nameof(type));
33 var shardKeyIndices =
new List<int>();
34 var shardKeyTypes =
new List<ColumnType>();
35 var decimalInfos =
new Dictionary<int, (int Precision, int Scale)>();
36 var charLengths =
new Dictionary<int, int>();
37 var columnNameToShardIndex =
new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
45 shardKeyIndices.Add(colIdx);
46 shardKeyTypes.Add(col.ColumnType);
47 columnNameToShardIndex[col.Name] = i;
50 bufferSize += GetColumnBufferSize(col.ColumnType, col.Properties, i, decimalInfos, charLengths);
53 _shardKeyIndices = shardKeyIndices;
54 _shardKeyTypes = shardKeyTypes;
55 _decimalInfos = decimalInfos;
56 _charLengths = charLengths;
57 _bufferSize = bufferSize;
58 _columnNameToShardIndex = columnNameToShardIndex;
67 throw new ArgumentNullException(nameof(ktype));
69 var shardKeyIndices =
new List<int>();
70 var shardKeyTypes =
new List<ColumnType>();
71 var decimalInfos =
new Dictionary<int, (int Precision, int Scale)>();
72 var charLengths =
new Dictionary<int, int>();
73 var columnNameToShardIndex =
new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
77 for (
int i = 0; i < columns.Count; i++)
80 var props = col.getProperties();
82 bool isKey = isPrimaryKey
88 var colType = DetermineColumnType(col);
89 shardKeyIndices.Add(i);
90 shardKeyTypes.Add(colType);
91 columnNameToShardIndex[col.getName()] = shardKeyIndices.Count - 1;
93 bufferSize += GetColumnBufferSizeFromKineticaColumn(col, shardKeyIndices.Count - 1, decimalInfos, charLengths);
97 _shardKeyIndices = shardKeyIndices;
98 _shardKeyTypes = shardKeyTypes;
99 _decimalInfos = decimalInfos;
100 _charLengths = charLengths;
101 _bufferSize = bufferSize;
102 _columnNameToShardIndex = columnNameToShardIndex;
108 public bool HasKey => _shardKeyIndices.Count > 0;
123 if (values.
Count != _shardKeyIndices.Count)
128 for (
int i = 0; i < values.
Count; i++)
130 var (name, value) = values[i];
133 if (!_columnNameToShardIndex.TryGetValue(name, out var shardIdx))
137 if (shardIdx >= _shardKeyTypes.Count)
141 var colType = _shardKeyTypes[shardIdx];
143 if (!AddValueToKey(key, value, colType, shardIdx))
161 case ColumnType.Integer:
162 case ColumnType.Int8:
163 case ColumnType.Int16:
164 case ColumnType.Boolean:
172 case ColumnType.Long:
173 case ColumnType.Timestamp:
181 case ColumnType.Float:
185 case ColumnType.Double:
189 case ColumnType.String:
190 case ColumnType.Char1:
191 case ColumnType.Char2:
192 case ColumnType.Char4:
193 case ColumnType.Char8:
194 case ColumnType.Char16:
195 case ColumnType.Char32:
196 case ColumnType.Char64:
197 case ColumnType.Char128:
198 case ColumnType.Char256:
199 if (value.
TryGetString(out var strVal) && strVal !=
null)
202 int charLen = _charLengths.TryGetValue(shardIdx, out var len) ? len : 0;
211 case ColumnType.Date:
212 if (value.
TryGetString(out var dateVal) && dateVal !=
null)
219 case ColumnType.DateTime:
227 case ColumnType.Time:
228 if (value.
TryGetString(out var timeVal) && timeVal !=
null)
235 case ColumnType.Ipv4:
243 case ColumnType.Decimal:
244 if (value.
TryGetString(out var decVal) && decVal !=
null)
246 var (precision, scale) = _decimalInfos.TryGetValue(shardIdx, out var info) ? info : (18, 4);
252 case ColumnType.Uuid:
253 if (value.
TryGetString(out var uuidVal) && uuidVal !=
null)
265 #region Buffer Size Calculation 267 private static int GetColumnBufferSize(
269 IReadOnlyList<string> properties,
271 Dictionary<
int, (
int Precision,
int Scale)> decimalInfos,
272 Dictionary<int, int> charLengths)
276 case ColumnType.Int8:
278 case ColumnType.Int16:
280 case ColumnType.Integer:
281 case ColumnType.Boolean:
282 case ColumnType.Ipv4:
283 case ColumnType.Time:
284 case ColumnType.Float:
286 case ColumnType.Long:
287 case ColumnType.Timestamp:
288 case ColumnType.Date:
289 case ColumnType.DateTime:
290 case ColumnType.Double:
291 case ColumnType.String:
292 case ColumnType.Uuid:
294 case ColumnType.Char1:
295 charLengths[shardIdx] = 1;
297 case ColumnType.Char2:
298 charLengths[shardIdx] = 2;
300 case ColumnType.Char4:
301 charLengths[shardIdx] = 4;
303 case ColumnType.Char8:
304 charLengths[shardIdx] = 8;
306 case ColumnType.Char16:
307 charLengths[shardIdx] = 16;
309 case ColumnType.Char32:
310 charLengths[shardIdx] = 32;
312 case ColumnType.Char64:
313 charLengths[shardIdx] = 64;
315 case ColumnType.Char128:
316 charLengths[shardIdx] = 128;
318 case ColumnType.Char256:
319 charLengths[shardIdx] = 256;
321 case ColumnType.Decimal:
323 foreach (var prop
in properties)
325 var match = Regex.Match(prop,
@"decimal\s*\(\s*(\d+)\s*,\s*(\d+)\s*\)", RegexOptions.IgnoreCase);
328 int precision =
int.Parse(match.Groups[1].Value);
329 int scale =
int.Parse(match.Groups[2].Value);
330 decimalInfos[shardIdx] = (precision, scale);
331 return precision > 18 ? 12 : 8;
334 decimalInfos[shardIdx] = (18, 4);
341 private static int GetColumnBufferSizeFromKineticaColumn(
344 Dictionary<
int, (
int Precision,
int Scale)> decimalInfos,
345 Dictionary<int, int> charLengths)
347 var props = col.getProperties();
349 if (props.Contains(
"int8"))
return 1;
350 if (props.Contains(
"int16"))
return 2;
351 if (props.Contains(
"ipv4") || props.Contains(
"time"))
return 4;
352 if (props.Contains(
"char1")) { charLengths[shardIdx] = 1;
return 1; }
353 if (props.Contains(
"char2")) { charLengths[shardIdx] = 2;
return 2; }
354 if (props.Contains(
"char4")) { charLengths[shardIdx] = 4;
return 4; }
355 if (props.Contains(
"char8")) { charLengths[shardIdx] = 8;
return 8; }
356 if (props.Contains(
"char16")) { charLengths[shardIdx] = 16;
return 16; }
357 if (props.Contains(
"char32")) { charLengths[shardIdx] = 32;
return 32; }
358 if (props.Contains(
"char64")) { charLengths[shardIdx] = 64;
return 64; }
359 if (props.Contains(
"char128")) { charLengths[shardIdx] = 128;
return 128; }
360 if (props.Contains(
"char256")) { charLengths[shardIdx] = 256;
return 256; }
362 foreach (var prop
in props)
364 var match = Regex.Match(prop,
@"decimal\s*\(\s*(\d+)\s*,\s*(\d+)\s*\)", RegexOptions.IgnoreCase);
367 int precision =
int.Parse(match.Groups[1].Value);
368 int scale =
int.Parse(match.Groups[2].Value);
369 decimalInfos[shardIdx] = (precision, scale);
370 return precision > 18 ? 12 : 8;
375 return col.getType()
switch 389 var props = col.getProperties();
391 if (props.Contains(
"boolean"))
return ColumnType.Boolean;
392 if (props.Contains(
"int8"))
return ColumnType.Int8;
393 if (props.Contains(
"int16"))
return ColumnType.Int16;
394 if (props.Contains(
"timestamp"))
return ColumnType.Timestamp;
395 if (props.Contains(
"date"))
return ColumnType.Date;
396 if (props.Contains(
"datetime"))
return ColumnType.DateTime;
397 if (props.Contains(
"time"))
return ColumnType.Time;
398 if (props.Contains(
"decimal"))
return ColumnType.Decimal;
399 if (props.Contains(
"ipv4"))
return ColumnType.Ipv4;
400 if (props.Contains(
"uuid"))
return ColumnType.Uuid;
401 if (props.Contains(
"char1"))
return ColumnType.Char1;
402 if (props.Contains(
"char2"))
return ColumnType.Char2;
403 if (props.Contains(
"char4"))
return ColumnType.Char4;
404 if (props.Contains(
"char8"))
return ColumnType.Char8;
405 if (props.Contains(
"char16"))
return ColumnType.Char16;
406 if (props.Contains(
"char32"))
return ColumnType.Char32;
407 if (props.Contains(
"char64"))
return ColumnType.Char64;
408 if (props.Contains(
"char128"))
return ColumnType.Char128;
409 if (props.Contains(
"char256"))
return ColumnType.Char256;
411 return col.getType()
switch 418 _ => ColumnType.String
RecordKeyBuilder(kinetica.KineticaType ktype, bool isPrimaryKey=false)
Creates a RecordKeyBuilder from a KineticaType (for backwards compatibility).
void AddUuid(string value)
Adds a UUID string to the key.
bool TryGetLong(out long value)
Tries to get the value as a long.
const string PRIMARY_KEY
This property indicates that this column will be part of (or the entire) primary key.
A binary key used for shard routing.
int Count
Gets the number of shard key values.
Column? GetColumn(int index)
Gets a column by index.
RecordKeyBuilder(Type type)
Creates a RecordKeyBuilder from a Type definition.
bool HasKey
Returns true if this builder has shard key columns.
void AddTime(string value)
Adds a time string (HH:MM:SS.mmm) to the key.
void AddIpv4(string value)
Adds an IPv4 address string (dotted-quad) to the key.
void AddDecimal(string value, int precision, int scale)
Adds a decimal string to the key.
Column properties used for Kinetica types.
void AddDateTime(string value)
Adds a datetime string (YYYY-MM-DD HH:MM:SS.mmm) to the key.
IReadOnlyList< int > ShardKeyIndices
Gets the shard key column indices.
float AsFloat()
Gets the value as a 32-bit float.
void AddCharN(string value, int length)
Adds a fixed-length char to the key.
void AddString(string value)
Adds a string to the key (via MurmurHash3).
IList< Column > getColumns()
Collection of shard key column names and values.
double AsDouble()
Gets the value as a 64-bit double.
Builds or creates RecordKey objects based on a given record.
const string SHARD_KEY
This property indicates that this column will be part of (or the entire) shard key.
Immutable collection of metadata about a Kinetica type.
void AddLong(long value)
Adds a 64-bit integer to the key (little-endian).
void AddDate(string value)
Adds a date string (YYYY-MM-DD) to the key.
A typed value for shard key computation.
RecordKey? Build(ShardKeyValues values)
Builds a RecordKey from the given shard key values.
void AddDouble(double value)
Adds a 64-bit double to the key.
void AddInt(int value)
Adds a 32-bit integer to the key (little-endian).
void AddFloat(float value)
Adds a 32-bit float to the key.
bool TryGetString(out string? value)
Tries to get the value as a string.
bool IsNull
Returns true if this value is null.
int KeyColumnCount
Gets the number of shard key columns.
bool TryGetInt(out int value)
Tries to get the value as an integer.