blob: fbf8870c5fb59db381676343e8671fa7699e9817 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include <stdint.h>
namespace doris {
/**
// Now only support text protocol
* helper for construct MySQL send row
* The MYSQL protocol:
*
* | flag | (length) | value | flag | (length) | value | ......
* <--------A column--------><--------A column--------><-.....->
*
* The flag means value's length or null value:
* If value is nullptr, flag is 251
* If value's length < 251, flag is the value's length
* If 251 <= value's length < 65536, flag is 252 and the next two bytes is length
* If 65536 <= value's length < 16777216 , flag is 253 and the next three bytes is length
* If 16777216 <= value's length, flag is 254 and the next eighth bytes is length
*
* the code example:
* mrb.push_null();
* mrb.push_tinyint(5);
* mrb.push_int(120);
* mrb.push_string("...my length is 65536...");
*
* the protocol contents:
*
* 251-1-'5'-3-'120'-253-65536-"...my length is 65536..."
*
*/
using int128_t = __int128;
class DecimalV2Value;
class IPv4Value;
class IPv6Value;
template <bool is_binary_format = false>
class MysqlRowBuffer {
public:
MysqlRowBuffer();
~MysqlRowBuffer();
void reset() { _pos = _buf; }
// Prepare for binary row buffer
// init bitmap
void start_binary_row(uint64_t num_cols);
// TODO(zhaochun): add signed/unsigned support
int push_tinyint(int8_t data);
int push_smallint(int16_t data);
int push_int(int32_t data);
int push_bigint(int64_t data);
int push_unsigned_bigint(uint64_t data);
int push_largeint(int128_t data);
int push_float(float data);
int push_double(double data);
int push_timev2(double data, int scale);
template <typename DateType>
int push_datetime(const DateType& data, int scale);
int push_decimal(const DecimalV2Value& data, int round_scale);
int push_ipv4(const IPv4Value& ipv4_val);
int push_ipv6(const IPv6Value& ipv6_val);
int push_string(const char* str, int64_t length);
int push_null();
template <typename DateType>
int push_vec_datetime(DateType& data, int scale = -1);
// this function reserved size, change the pos step size, return old pos
// Becareful when use the returned pointer.
char* reserved(int64_t size);
const char* buf() const { return _buf; }
const char* pos() const { return _pos; }
int64_t length() const { return _pos - _buf; }
/**
* Why?
* Because the Nested-Type's data need pushed multiple times, but mysql protocol don't
* support nested type and each push will decide a column data.
*
* How?
* Dynamic mode allow we push data in a column multiple times, and allow recursive push.
* We will think that the length of the next column is uncertain when open dynamic
* mode, so we will set the flag to 254(longest flag) and skip 8 bytes which used for
* record length, then compute the actual data length when close dynamic mode.
* In a recursive call(special for nested type), the mode will open multiple times, but
* the data is actually written in one column, so we only need to deal it at the beginning
* and at the end.
*
* the code:
* mrb.push_tinyint(5);
* mrb.push_smallint(120);
* mrb.push_int(-30000);
*
* In normal mode, the buffer contains three column:
* 1-'5'-3-'120'-6-'-30000'
*
* Same code in dynamic mode, the buffer contains a column:
* 254-48-'5'-'120'-'-30000'
*
* NOTE: The open_dynamic_mode() and close_dynamic_mode() need appear in pairs
*/
void open_dynamic_mode();
/**
* NOTE: The open_dynamic_mode() and close_dynamic_mode() need appear in pairs
*/
void close_dynamic_mode();
private:
int reserve(int64_t size);
// append data into buffer
int append(const char* data, int64_t len);
// the same as mysql net_store_data
// the first few bytes is length, followed by data
int append_var_string(const char* data, int64_t len);
char* _pos = nullptr;
char* _buf = nullptr;
int64_t _buf_size;
char _default_buf[4096];
int _dynamic_mode;
uint64_t _len_pos;
uint32_t _field_pos = 0;
uint32_t _field_count = 0;
};
} // namespace doris