Files
doris/be/src/util/mysql_row_buffer.cpp
chenhao7253886 37b4cafe87 Change variable and namespace name in BE (#268)
Change 'palo' to 'doris'
2018-11-02 10:22:32 +08:00

300 lines
7.1 KiB
C++

// 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.
#include "util/mysql_row_buffer.h"
#include <stdio.h>
#include <stdlib.h>
#include "common/logging.h"
#include "gutil/strings/numbers.h"
#include "util/mysql_global.h"
namespace doris {
// the first byte:
// <= 250: length
// = 251: NULL
// = 252: the next two byte is length
// = 253: the next three byte is length
// = 254: the next eighth byte is length
static char* pack_vlen(char* packet, uint64_t length) {
if (length < 251ULL) {
int1store(packet, length);
return packet + 1;
}
/* 251 is reserved for NULL */
if (length < 65536ULL) {
*packet++ = 252;
int2store(packet, length);
return packet + 2;
}
if (length < 16777216ULL) {
*packet++ = 253;
int3store(packet, length);
return packet + 3;
}
*packet++ = 254;
int8store(packet, length);
return packet + 8;
}
MysqlRowBuffer::MysqlRowBuffer():
_pos(_default_buf),
_buf(_default_buf),
_buf_size(sizeof(_default_buf)) {
}
MysqlRowBuffer::~MysqlRowBuffer() {
if (_buf != _default_buf) {
delete[] _buf;
}
}
int MysqlRowBuffer::reserve(int size) {
if (size < 0) {
LOG(ERROR) << "alloc memory failed. size = " << size;
return -1;
}
int need_size = size + (_pos - _buf);
if (need_size <= _buf_size) {
return 0;
}
int alloc_size = std::max(need_size, _buf_size * 2);
char* new_buf = new(std::nothrow) char[alloc_size];
if (NULL == new_buf) {
LOG(ERROR) << "alloc memory failed. size = " << alloc_size;
return -1;
}
memcpy(new_buf, _buf, _pos - _buf);
if (_buf != _default_buf) {
delete[] _buf;
}
_pos = new_buf + (_pos - _buf);
_buf = new_buf;
_buf_size = alloc_size;
return 0;
}
int MysqlRowBuffer::push_tinyint(int8_t data) {
// 1 for string trail, 1 for length, 1 for sign, other for digits
int ret = reserve(3 + MAX_TINYINT_WIDTH);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
int length = snprintf(_pos + 1, MAX_TINYINT_WIDTH + 2, "%d", data);
if (length < 0) {
LOG(ERROR) << "snprintf failed. data = " << data;
return length;
}
int1store(_pos, length);
_pos += length + 1;
return 0;
}
int MysqlRowBuffer::push_smallint(int16_t data) {
// 1 for string trail, 1 for length, 1 for sign, other for digits
int ret = reserve(3 + MAX_SMALLINT_WIDTH);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
int length = snprintf(_pos + 1, MAX_SMALLINT_WIDTH + 2, "%d", data);
if (length < 0) {
LOG(ERROR) << "snprintf failed. data = " << data;
return length;
}
int1store(_pos, length);
_pos += length + 1;
return 0;
}
int MysqlRowBuffer::push_int(int32_t data) {
// 1 for string trail, 1 for length, 1 for sign, other for digits
int ret = reserve(3 + MAX_INT_WIDTH);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
int length = snprintf(_pos + 1, MAX_INT_WIDTH + 2, "%d", data);
if (length < 0) {
LOG(ERROR) << "snprintf failed. data = " << data;
return length;
}
int1store(_pos, length);
_pos += length + 1;
return 0;
}
int MysqlRowBuffer::push_bigint(int64_t data) {
// 1 for string trail, 1 for length, 1 for sign, other for digits
int ret = reserve(3 + MAX_BIGINT_WIDTH);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
int length = snprintf(_pos + 1, MAX_BIGINT_WIDTH + 2, "%ld", data);
if (length < 0) {
LOG(ERROR) << "snprintf failed. data = " << data;
return length;
}
int1store(_pos, length);
_pos += length + 1;
return 0;
}
int MysqlRowBuffer::push_unsigned_bigint(uint64_t data) {
// 1 for string trail, 1 for length, 1 for sign, other for digits
int ret = reserve(4 + MAX_BIGINT_WIDTH);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
int length = snprintf(_pos + 1, MAX_BIGINT_WIDTH + 3, "%ld", data);
if (length < 0) {
LOG(ERROR) << "snprintf failed. data = " << data;
return length;
}
int1store(_pos, length);
_pos += length + 1;
return 0;
}
int MysqlRowBuffer::push_float(float data) {
// 1 for string trail, 1 for length, 1 for sign, other for digits
int ret = reserve(3 + MAX_FLOAT_STR_LENGTH);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
int length = FloatToBuffer(data, MAX_FLOAT_STR_LENGTH + 2, _pos + 1);
if (length < 0) {
LOG(ERROR) << "gcvt float failed. data = " << data;
return length;
}
int1store(_pos, length);
_pos += length + 1;
return 0;
}
int MysqlRowBuffer::push_double(double data) {
// 1 for string trail, 1 for length, 1 for sign, other for digits
int ret = reserve(3 + MAX_DOUBLE_STR_LENGTH);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
int length = DoubleToBuffer(data, MAX_DOUBLE_STR_LENGTH + 2, _pos + 1);
if (length < 0) {
LOG(ERROR) << "gcvt double failed. data = " << data;
return length;
}
int1store(_pos, length);
_pos += length + 1;
return 0;
}
int MysqlRowBuffer::push_string(const char* str, int length) {
// 9 for length pack max, 1 for sign, other for digits
if (NULL == str) {
LOG(ERROR) << "input string is NULL.";
return -1;
}
int ret = reserve(9 + length);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
_pos = pack_vlen(_pos, length);
memcpy(_pos, str, length);
_pos += length;
return 0;
}
int MysqlRowBuffer::push_null() {
int ret = reserve(1);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return ret;
}
int1store(_pos, 251);
_pos += 1;
return 0;
}
char* MysqlRowBuffer::reserved(int size) {
int ret = reserve(size);
if (0 != ret) {
LOG(ERROR) << "mysql row buffer reserver failed.";
return NULL;
}
char* old_buf = _pos;
_pos += size;
return old_buf;
}
}
/* vim: set ts=4 sw=4 sts=4 tw=100 */