public long GetInt64(int columnIndex) { CheckType(columnIndex, KuduTypeFlags.Int64 | KuduTypeFlags.UnixtimeMicros); CheckValue(columnIndex); ReadOnlySpan <byte> data = GetRowAllocColumn(columnIndex, 8); return(KuduEncoder.DecodeInt64(data)); }
/// <summary> /// Increments the column at the given index, returning false if the /// value is already the maximum. /// </summary> /// <param name="index">The column index to increment.</param> internal bool IncrementColumn(int index) { if (!IsSet(index)) { throw new ArgumentException($"Column index {index} has not been set."); } ColumnSchema column = Schema.GetColumn(index); if (column.IsFixedSize) { KuduType type = column.Type; Span <byte> data = GetRowAllocColumn(index, column.Size); switch (type) { case KuduType.Bool: { bool isFalse = data[0] == 0; data[0] = 1; return(isFalse); } case KuduType.Int8: { sbyte existing = KuduEncoder.DecodeInt8(data); if (existing == sbyte.MaxValue) { return(false); } KuduEncoder.EncodeInt8(data, (sbyte)(existing + 1)); return(true); } case KuduType.Int16: { short existing = KuduEncoder.DecodeInt16(data); if (existing == short.MaxValue) { return(false); } KuduEncoder.EncodeInt16(data, (short)(existing + 1)); return(true); } case KuduType.Int32: { int existing = KuduEncoder.DecodeInt32(data); if (existing == int.MaxValue) { return(false); } KuduEncoder.EncodeInt32(data, existing + 1); return(true); } case KuduType.Date: { int existing = KuduEncoder.DecodeInt32(data); if (existing == EpochTime.MaxDateValue) { return(false); } KuduEncoder.EncodeInt32(data, existing + 1); return(true); } case KuduType.Int64: case KuduType.UnixtimeMicros: { long existing = KuduEncoder.DecodeInt64(data); if (existing == long.MaxValue) { return(false); } KuduEncoder.EncodeInt64(data, existing + 1); return(true); } case KuduType.Float: { float existing = KuduEncoder.DecodeFloat(data); float incremented = existing.NextUp(); if (existing == incremented) { return(false); } KuduEncoder.EncodeFloat(data, incremented); return(true); } case KuduType.Double: { double existing = KuduEncoder.DecodeDouble(data); double incremented = existing.NextUp(); if (existing == incremented) { return(false); } KuduEncoder.EncodeDouble(data, incremented); return(true); } case KuduType.Decimal32: { int existing = KuduEncoder.DecodeInt32(data); int precision = column.TypeAttributes !.Precision.GetValueOrDefault(); if (existing == DecimalUtil.MaxDecimal32(precision)) { return(false); } KuduEncoder.EncodeInt32(data, existing + 1); return(true); } case KuduType.Decimal64: { long existing = KuduEncoder.DecodeInt64(data); int precision = column.TypeAttributes !.Precision.GetValueOrDefault(); if (existing == DecimalUtil.MaxDecimal64(precision)) { return(false); } KuduEncoder.EncodeInt64(data, existing + 1); return(true); } case KuduType.Decimal128: { KuduInt128 existing = KuduEncoder.DecodeInt128(data); int precision = column.TypeAttributes !.Precision.GetValueOrDefault(); if (existing == DecimalUtil.MaxDecimal128(precision)) { return(false); } KuduEncoder.EncodeInt128(data, existing + 1); return(true); } default: throw new Exception($"Unsupported data type {type}"); } } else { // Column is either string, binary, or varchar. ReadOnlySpan <byte> data = GetVarLengthColumn(index); var incremented = new byte[data.Length + 1]; data.CopyTo(incremented); WriteBinary(index, incremented); return(true); } }
// Used to convert the rowwise data to the newer columnar format, // to avoid virtual calls on ResultSet. // This is only used if the Kudu server is 1.11 or older. public static ResultSet Convert( KuduMessage message, KuduSchema schema, RowwiseRowBlockPB rowPb) { var numColumns = schema.Columns.Count; int columnOffsetsSize = numColumns; if (schema.HasNullableColumns) { columnOffsetsSize++; } var columnOffsets = new int[columnOffsetsSize]; int currentOffset = 0; columnOffsets[0] = currentOffset; // Pre-compute the columns offsets in rowData for easier lookups later. // If the schema has nullables, we also add the offset for the null bitmap at the end. for (int i = 1; i < columnOffsetsSize; i++) { ColumnSchema column = schema.GetColumn(i - 1); int previousSize = column.Size; columnOffsets[i] = previousSize + currentOffset; currentOffset += previousSize; } var rowData = GetRowData(message, rowPb); var indirectData = GetIndirectData(message, rowPb); int nonNullBitmapOffset = columnOffsets[columnOffsets.Length - 1]; int rowSize = schema.RowSize; int numRows = rowPb.NumRows; var dataSidecarOffsets = new SidecarOffset[numColumns]; var varlenDataSidecarOffsets = new SidecarOffset[numColumns]; var nonNullBitmapSidecarOffsets = new SidecarOffset[numColumns]; int nonNullBitmapSize = KuduEncoder.BitsToBytes(numRows); int offset = 0; for (int i = 0; i < numColumns; i++) { var column = schema.GetColumn(i); var dataSize = column.IsFixedSize ? column.Size * numRows : (4 * numRows) + 4; dataSidecarOffsets[i] = new SidecarOffset(offset, dataSize); offset += dataSize; if (column.IsNullable) { nonNullBitmapSidecarOffsets[i] = new SidecarOffset(offset, nonNullBitmapSize); offset += nonNullBitmapSize; } else { nonNullBitmapSidecarOffsets[i] = new SidecarOffset(-1, 0); } } var buffer = new ArrayPoolBuffer <byte>(offset + indirectData.Length); var data = buffer.Buffer; data.AsSpan().Clear(); var varlenData = data.AsSpan(offset); int currentDataOffset = 0; int currentVarlenOffset = 0; for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) { var column = schema.GetColumn(columnIndex); var isFixedSize = column.IsFixedSize; var columnarSize = isFixedSize ? column.Size : 4; var rowwiseSize = column.Size; var dataOffset = dataSidecarOffsets[columnIndex]; var nonNullOffset = nonNullBitmapSidecarOffsets[columnIndex].Start; var dataOutput = data.AsSpan(dataOffset.Start, dataOffset.Length); for (int rowIndex = 0; rowIndex < numRows; rowIndex++) { bool isSet = true; var rowSlice = rowData.Slice(rowSize * rowIndex, rowSize); if (nonNullOffset > 0) { isSet = !rowSlice.GetBit(nonNullBitmapOffset, columnIndex); if (isSet) { data.SetBit(nonNullOffset, rowIndex); } } if (isSet) { if (isFixedSize) { var rawData = rowSlice.Slice(currentDataOffset, columnarSize); rawData.CopyTo(dataOutput); } else { var offsetData = rowSlice.Slice(currentDataOffset, 8); var lengthData = rowSlice.Slice(currentDataOffset + 8, 8); int start = (int)KuduEncoder.DecodeInt64(offsetData); int length = (int)KuduEncoder.DecodeInt64(lengthData); var indirectSlice = indirectData.Slice(start, length); indirectSlice.CopyTo(varlenData); varlenData = varlenData.Slice(length); KuduEncoder.EncodeInt32(dataOutput, currentVarlenOffset); currentVarlenOffset += length; } } dataOutput = dataOutput.Slice(columnarSize); } currentDataOffset += rowwiseSize; if (!isFixedSize) { KuduEncoder.EncodeInt32(dataOutput, currentVarlenOffset); varlenDataSidecarOffsets[columnIndex] = new SidecarOffset(offset, currentVarlenOffset); offset += currentVarlenOffset; currentVarlenOffset = 0; } } return(new ResultSet( buffer, schema, numRows, dataSidecarOffsets, varlenDataSidecarOffsets, nonNullBitmapSidecarOffsets)); }