2
* Copyright (c) 2021 OceanBase
3
* OceanBase CE is licensed under Mulan PubL v2.
4
* You can use this software according to the terms and conditions of the Mulan PubL v2.
5
* You may obtain a copy of Mulan PubL v2 at:
6
* http://license.coscl.org.cn/MulanPubL-2.0
7
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10
* See the Mulan PubL v2 for more details.
13
#define USING_LOG_PREFIX SERVER
15
#include "ob_query_driver.h"
16
#include "ob_mysql_result_set.h"
19
#include "rpc/obmysql/packet/ompk_row.h"
20
#include "rpc/obmysql/packet/ompk_resheader.h"
21
#include "rpc/obmysql/packet/ompk_field.h"
22
#include "rpc/obmysql/packet/ompk_eof.h"
24
#include "share/ob_lob_access_utils.h"
25
#include "lib/charset/ob_charset.h"
26
#include "observer/mysql/obmp_stmt_prexecute.h"
27
#ifdef OB_BUILD_ORACLE_XML
28
#include "lib/xml/ob_multi_mode_interface.h"
29
#include "lib/xml/ob_xml_util.h"
30
#include "sql/engine/expr/ob_expr_xml_func_helper.h"
35
using namespace common;
37
using namespace obmysql;
41
int ObQueryDriver::response_query_header(ObResultSet &result,
43
bool need_set_ps_out_flag,
44
bool need_flush_buffer)
48
// 二合一协议发送 header 包, 不单独发送 column
49
if (OB_FAIL(static_cast<ObMPStmtPrexecute&>(sender_).response_query_header(session_, result, need_flush_buffer))) {
50
LOG_WARN("prexecute response query head fail. ", K(ret));
53
if (NULL == result.get_field_columns()) {
54
ret = OB_INVALID_ARGUMENT;
55
LOG_WARN("response field is null. ", K(ret));
56
} else if (OB_FAIL(response_query_header(*result.get_field_columns(),
61
LOG_WARN("response query head fail. ", K(ret));
65
result.set_errcode(ret);
70
int ObQueryDriver::response_query_header(const ColumnsFieldIArray &fields,
72
bool need_set_ps_out_flag,
73
bool ps_cursor_execute,
78
// result == null means ps cursor in execute or fetch .
79
if (NULL != result && (&fields != result->get_field_columns())) {
80
ret = OB_ERR_UNEXPECTED;
81
LOG_WARN("filed is not from result in non ps cursor mode. ", K(ret));
82
} else if (fields.count() <= 0) {
83
LOG_WARN("column cnt is null ", K(fields.count()));
84
ret = OB_ERR_BAD_FIELD_ERROR;
85
} else if (OB_FAIL(session_.get_autocommit(ac))) {
86
LOG_WARN("fail to get autocommit", K(ret));
87
} else if (!(NULL != result && result->get_is_com_filed_list())) {
90
rhp.set_field_count(fields.count());
91
if (OB_FAIL(sender_.response_packet(rhp, &session_))) {
92
LOG_WARN("response packet fail", K(ret));
95
// com field 协议在这里什么都不发,直接发送 field 信息
100
for (int64_t i = 0; OB_SUCC(ret) && i < fields.count(); ++i) {
101
bool is_not_match = false;
103
const ObField &ob_field = fields.at(i);
104
if (NULL != result && result->get_is_com_filed_list()
105
&& OB_FAIL(is_com_filed_list_match_wildcard_str(
107
static_cast<ObCollationType>(ob_field.charsetnr_),
110
LOG_WARN("failed to is com filed list match wildcard str", K(ret));
111
} else if (is_not_match) {
114
ret = ObMySQLResultSet::to_mysql_field(ob_field, field);
116
ObMySQLResultSet::replace_lob_type(session_, ob_field, field);
117
if (NULL != result && result->get_is_com_filed_list()) {
118
field.default_value_ = static_cast<EMySQLFieldType>(ob_field.default_value_.get_ext());
121
if (OB_FAIL(sender_.response_packet(fp, &session_))) {
122
LOG_WARN("response packet fail", K(ret));
131
eofp.set_warning_count(0);
132
ObServerStatusFlags flags = eofp.get_server_status();
133
flags.status_flags_.OB_SERVER_STATUS_IN_TRANS
134
= (session_.is_server_status_in_transaction() ? 1 : 0);
135
flags.status_flags_.OB_SERVER_STATUS_AUTOCOMMIT = (ac ? 1 : 0);
136
flags.status_flags_.OB_SERVER_MORE_RESULTS_EXISTS = has_more_result;
137
flags.status_flags_.OB_SERVER_PS_OUT_PARAMS = need_set_ps_out_flag ? 1 : 0;
138
// NULL == result 说明是老协议 ps cursor execute 回包,或者fetch 协议回包, cursor_exit = true
139
flags.status_flags_.OB_SERVER_STATUS_CURSOR_EXISTS = NULL == result ? 1 : 0;
140
if (!session_.is_obproxy_mode()) {
141
// in java client or others, use slow query bit to indicate partition hit or not
142
flags.status_flags_.OB_SERVER_QUERY_WAS_SLOW = !session_.partition_hit().get_bool();
144
eofp.set_server_status(flags);
146
if (ps_cursor_execute && sender_.need_send_extra_ok_packet()) {
147
// 老协议 ps cursor execute 回包, 只回 field 信息, 所以对于 proxy , 需要额外回一个 OK包
148
// 但是由于 2.0 协议需要在回 OK 包的同时了解 EOF 包的情况,所以这个 OK 包没办法抽到 execute 协议层处理
149
if (OB_FAIL(sender_.update_last_pkt_pos())) {
150
LOG_WARN("failed to update last packet pos", K(ret));
152
// in multi-stmt, send extra ok packet in the last stmt(has no more result)
154
ok_param.affected_rows_ = 0;
155
ok_param.is_partition_hit_ = session_.partition_hit().get_bool();
156
ok_param.has_more_result_ = false;
157
if (OB_FAIL(sender_.send_ok_packet(session_, ok_param, &eofp))) {
158
LOG_WARN("fail to send ok packt", K(ok_param), K(ret));
162
if (OB_FAIL(sender_.response_packet(eofp, &session_))) {
163
LOG_WARN("response packet fail", K(ret));
170
int ObQueryDriver::response_query_result(ObResultSet &result,
172
bool has_more_result,
176
int ret = OB_SUCCESS;
177
FLTSpanGuard(response_result);
179
bool is_first_row = true;
180
const ObNewRow *result_row = NULL;
181
bool has_top_limit = result.get_has_top_limit();
182
bool is_cac_found_rows = result.is_calc_found_rows();
183
int64_t limit_count = OB_INVALID_COUNT == fetch_limit ? INT64_MAX : fetch_limit;
185
ObSqlCtx *sql_ctx = result.get_exec_context().get_sql_ctx();
186
if (!has_top_limit && OB_INVALID_COUNT == fetch_limit) {
187
limit_count = INT64_MAX;
188
if (!lib::is_oracle_mode()) {
189
if (OB_FAIL(session_.get_sql_select_limit(limit_count))) {
190
LOG_WARN("fail tp get sql select limit", K(ret));
194
bool is_packed = result.get_physical_plan() ? result.get_physical_plan()->is_packed() : false;
195
MYSQL_PROTOCOL_TYPE protocol_type = is_ps_protocol ? MYSQL_PROTOCOL_TYPE::BINARY : MYSQL_PROTOCOL_TYPE::TEXT;
196
const common::ColumnsFieldIArray *fields = NULL;
198
fields = result.get_field_columns();
199
if (OB_ISNULL(fields)) {
200
ret = OB_INVALID_ARGUMENT;
201
LOG_WARN("fields is null", K(ret), KP(fields));
204
while (OB_SUCC(ret) && row_num < limit_count && !OB_FAIL(result.get_next_row(result_row)) ) {
205
ObNewRow *row = const_cast<ObNewRow*>(result_row);
206
if (is_prexecute_ && row_num == limit_count - 1) {
207
LOG_DEBUG("is_prexecute_ and row_num is equal with limit_count", K(limit_count));
210
// 如果是第一行,则先给客户端回复field等信息
212
is_first_row = false;
213
can_retry = false; // 已经获取到第一行数据,不再重试了
215
if (OB_NOT_NULL(result.get_exec_context().get_physical_plan_ctx()) &&
216
OB_NOT_NULL(sql_ctx) && sql_ctx->spm_ctx_.need_spm_timeout_) {
217
LOG_TRACE("reset to origin timeout because result is returning to user");
218
result.get_exec_context().get_physical_plan_ctx()->set_spm_timeout_timestamp(0);
221
if (OB_FAIL(response_query_header(result, has_more_result, false))) {
222
LOG_WARN("fail to response query header", K(ret), K(row_num), K(can_retry));
225
for (int64_t i = 0; OB_SUCC(ret) && i < row->get_count(); i++) {
226
ObObj& value = row->get_cell(i);
227
if (result.is_ps_protocol() && !is_packed) {
228
if (value.get_type() != fields->at(i).type_.get_type()) {
229
ObCastCtx cast_ctx(&result.get_mem_pool(), NULL, CM_WARN_ON_FAIL,
230
fields->at(i).type_.get_collation_type());
231
if (OB_FAIL(common::ObObjCaster::to_type(fields->at(i).type_.get_type(),
235
LOG_WARN("failed to cast object", K(ret), K(value),
236
K(value.get_type()), K(fields->at(i).type_.get_type()));
240
if (OB_SUCC(ret) && !is_packed) {
241
// cluster version < 4.1
242
// use only locator and response routine
243
// >= 4.1 for oracle modle
244
// 1. user full lob locator v2 with extern header if client supports locator
245
// 2. remove locator if client does not support locator
246
// >= 4.1 for mysql modle
248
if (ob_is_string_tc(value.get_type())
249
&& CS_TYPE_INVALID != value.get_collation_type()) {
250
OZ(convert_string_value_charset(value, result));
251
} else if (value.is_clob_locator()
252
&& OB_FAIL(convert_lob_value_charset(value, result))) {
253
LOG_WARN("convert lob value charset failed", K(ret));
254
} else if (ob_is_text_tc(value.get_type())
255
&& OB_FAIL(convert_text_value_charset(value, result))) {
256
LOG_WARN("convert text value charset failed", K(ret));
259
} else if ((value.is_lob() || value.is_lob_locator() || value.is_json() || value.is_geometry())
260
&& OB_FAIL(process_lob_locator_results(value, result))) {
261
LOG_WARN("convert lob locator to longtext failed", K(ret));
262
#ifdef OB_BUILD_ORACLE_XML
263
} else if (value.is_user_defined_sql_type() && OB_FAIL(ObXMLExprHelper::process_sql_udt_results(value, result))) {
264
LOG_WARN("convert udt to client format failed", K(ret), K(value.get_udt_subschema_id()));
270
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(&session_);
271
ObSMRow sm(protocol_type, *row, dtc_params,
272
result.get_field_columns(),
274
session_.get_effective_tenant_id());
275
sm.set_packed(is_packed);
277
rp.set_is_packed(is_packed);
278
if (OB_FAIL(sender_.response_packet(rp, &result.get_session()))) {
279
LOG_WARN("response packet fail", K(ret), KP(row), K(row_num),
283
LOG_DEBUG("response row succ", K(*row));
287
if (0 == row_num % RESET_CONVERT_CHARSET_ALLOCATOR_EVERY_X_ROWS) {
288
(void) result.get_exec_context().try_reset_convert_charset_allocator();
293
if (is_cac_found_rows) {
294
while (OB_SUCC(ret) && !OB_FAIL(result.get_next_row(result_row))) {
298
if (OB_ITER_END == ret) {
301
LOG_WARN("fail to iterate and response", K(ret), K(row_num), K(can_retry));
303
if (OB_SUCC(ret) && 0 == row_num) {
304
// 如果是一行数据也没有,则还是要给客户端回复field等信息,并且不再重试了
306
if (OB_FAIL(response_query_header(result, has_more_result, false))) {
307
LOG_WARN("fail to response query header", K(ret), K(row_num), K(can_retry));
310
if (OB_FAIL(ret) && !can_retry) {
311
FLOG_INFO("The query has already returned partial results to the client and cannot be retried", KR(ret));
317
int ObQueryDriver::convert_field_charset(ObIAllocator& allocator,
318
const ObCollationType& from_collation,
319
const ObCollationType& dest_collation,
320
const ObString &from_string,
321
ObString &dest_string)
323
int ret = OB_SUCCESS;
325
int32_t buf_len = from_string.length() * ObCharset::CharConvertFactorNum;
326
uint32_t result_len = 0;
328
} else if (OB_UNLIKELY(NULL == (buf = static_cast<char*>(
329
allocator.alloc(buf_len))))) {
330
ret = OB_ALLOCATE_MEMORY_FAILED;
331
LOG_ERROR("alloc memory failed", K(ret));
332
} else if (OB_FAIL(ObCharset::charset_convert(
333
static_cast<ObCollationType>(from_collation),
335
from_string.length(),
340
LOG_WARN("charset convert failed", K(ret), K(from_collation), K(dest_collation));
342
dest_string.assign(buf, static_cast<int32_t>(result_len));
347
int ObQueryDriver::convert_string_value_charset(ObObj& value, ObResultSet &result)
349
int ret = OB_SUCCESS;
350
ObCharsetType charset_type = CHARSET_INVALID;
351
const ObSQLSessionInfo &my_session = result.get_session();
352
ObArenaAllocator *allocator = NULL;
353
ObCollationType from_collation_type = value.get_collation_type();
354
ObCollationType to_collation_type = CS_TYPE_INVALID;
355
ObCharsetType nchar = CHARSET_INVALID;
356
if (OB_FAIL(my_session.get_ncharacter_set_connection(nchar))) {
357
LOG_WARN("get ncharacter set connection failed", K(ret));
358
} else if (lib::is_oracle_mode()
359
&& (value.is_nchar() || value.is_nvarchar2())
360
&& nchar != CHARSET_INVALID
361
&& nchar != CHARSET_BINARY) {
362
to_collation_type = ObCharset::get_default_collation(nchar);
363
charset_type = nchar;
364
} else if (OB_FAIL(my_session.get_character_set_results(charset_type))) {
365
LOG_WARN("fail to get result charset", K(ret));
367
to_collation_type = ObCharset::get_default_collation(charset_type);
370
} else if (from_collation_type == to_collation_type) {
371
const ObCharsetInfo *charset_info = ObCharset::get_charset(from_collation_type);
372
if (OB_ISNULL(charset_info)) {
373
ret = OB_ERR_UNEXPECTED;
374
LOG_WARN("charsetinfo is null", K(ret), K(from_collation_type), K(to_collation_type), K(value));
375
} else if (CS_TYPE_INVALID == from_collation_type) {
376
ret = OB_ERR_UNEXPECTED;
377
LOG_WARN("invalid collation", K(ret), K(from_collation_type), K(to_collation_type), K(value));
379
} else if (OB_FAIL(result.get_exec_context().get_convert_charset_allocator(allocator))) {
380
LOG_WARN("fail to get lob fake allocator", K(ret));
381
} else if (OB_ISNULL(allocator)) {
382
ret = OB_ERR_UNEXPECTED;
383
LOG_WARN("lob fake allocator is null.", K(ret), K(value));
385
OZ (value.convert_string_value_charset(charset_type, *allocator));
390
int ObQueryDriver::convert_string_value_charset(ObObj& value,
391
ObCharsetType charset_type,
392
ObIAllocator &allocator)
394
int ret = OB_SUCCESS;
396
value.get_string(str);
397
if (ObCharset::is_valid_charset(charset_type) && CHARSET_BINARY != charset_type) {
398
ObCollationType collation_type = ObCharset::get_default_collation(charset_type);
399
const ObCharsetInfo *from_charset_info = ObCharset::get_charset(value.get_collation_type());
400
const ObCharsetInfo *to_charset_info = ObCharset::get_charset(collation_type);
401
if (OB_ISNULL(from_charset_info) || OB_ISNULL(to_charset_info)) {
402
ret = OB_ERR_UNEXPECTED;
403
LOG_WARN("charsetinfo is null", K(ret), K(value.get_collation_type()), K(collation_type));
404
} else if (CS_TYPE_INVALID == value.get_collation_type() || CS_TYPE_INVALID == collation_type) {
405
ret = OB_ERR_UNEXPECTED;
406
LOG_WARN("invalid collation", K(value.get_collation_type()), K(collation_type), K(ret));
407
} else if (CS_TYPE_BINARY != value.get_collation_type() && CS_TYPE_BINARY != collation_type
408
&& strcmp(from_charset_info->csname, to_charset_info->csname) != 0) {
410
int32_t buf_len = str.length() * ObCharset::CharConvertFactorNum;
411
uint32_t result_len = 0;
414
} else if (OB_UNLIKELY(NULL == (buf = static_cast<char *>(
415
allocator.alloc(buf_len))))) {
416
ret = OB_ALLOCATE_MEMORY_FAILED;
417
LOG_ERROR("alloc memory failed", K(ret), K(buf_len));
418
} else if (OB_FAIL(convert_string_charset(str, value.get_collation_type(),
419
collation_type, buf, buf_len, result_len))) {
420
LOG_WARN("convert string charset failed", K(ret));
422
value.set_string(value.get_type(), buf, static_cast<int32_t>(result_len));
423
value.set_collation_type(collation_type);
430
int ObQueryDriver::convert_lob_value_charset(common::ObObj& value, sql::ObResultSet &result)
432
int ret = OB_SUCCESS;
434
ObCharsetType charset_type = CHARSET_INVALID;
435
ObCharsetType nchar = CHARSET_INVALID;
436
const ObSQLSessionInfo &my_session = result.get_session();
437
ObArenaAllocator *allocator = NULL;
438
if (OB_FAIL(result.get_exec_context().get_convert_charset_allocator(allocator))) {
439
LOG_WARN("fail to get lob fake allocator", K(ret));
440
} else if (OB_ISNULL(allocator)) {
441
ret = OB_ERR_UNEXPECTED;
442
LOG_WARN("lob fake allocator is null.", K(ret), K(value));
443
} else if (OB_FAIL(my_session.get_character_set_results(charset_type))) {
444
LOG_WARN("fail to get result charset", K(ret));
445
} else if (OB_FAIL(my_session.get_ncharacter_set_connection(nchar))) {
446
LOG_WARN("get ncharacter set connection failed", K(ret));
447
} else if (lib::is_oracle_mode()
448
&& (value.is_nchar() || value.is_nvarchar2())
449
&& nchar != CHARSET_INVALID
450
&& nchar != CHARSET_BINARY) {
451
charset_type = nchar;
454
} else if (OB_FAIL(convert_lob_value_charset(value, charset_type, *allocator))) {
455
LOG_WARN("convert lob value fail.", K(ret), K(value));
460
int ObQueryDriver::convert_text_value_charset(common::ObObj& value, sql::ObResultSet &result)
462
int ret = OB_SUCCESS;
463
ObCharsetType charset_type = CHARSET_INVALID;
464
ObCharsetType nchar = CHARSET_INVALID;
465
const ObSQLSessionInfo &my_session = result.get_session();
466
ObArenaAllocator *allocator = NULL;
467
if (OB_FAIL(result.get_exec_context().get_convert_charset_allocator(allocator))) {
468
LOG_WARN("fail to get lob fake allocator", K(ret));
469
} else if (OB_ISNULL(allocator)) {
470
ret = OB_ERR_UNEXPECTED;
471
LOG_WARN("text fake allocator is null.", K(ret), K(value));
472
} else if (OB_FAIL(my_session.get_character_set_results(charset_type))) {
473
LOG_WARN("fail to get result charset", K(ret));
474
} else if (OB_FAIL(my_session.get_ncharacter_set_connection(nchar))) {
475
LOG_WARN("get ncharacter set connection failed", K(ret));
476
} else if (lib::is_oracle_mode()
477
&& (value.is_nchar() || value.is_nvarchar2())
478
&& nchar != CHARSET_INVALID
479
&& nchar != CHARSET_BINARY) {
480
charset_type = nchar;
483
} else if (OB_FAIL(convert_text_value_charset(value, charset_type, *allocator, &my_session))) {
484
LOG_WARN("convert lob value fail.", K(ret), K(value));
489
int ObQueryDriver::like_match(const char* str, int64_t length_str, int64_t i,
490
const char* pattern, int64_t length_pat, int64_t j,
493
int ret = OB_SUCCESS;
494
bool is_stack_overflow = false;
495
if (OB_ISNULL(str) || OB_ISNULL(pattern) ||
496
OB_UNLIKELY(length_str < 0 || i < 0 || length_pat < 0 || j < 0)) {
497
ret = OB_ERR_UNEXPECTED;
498
LOG_WARN("get unexpected error", K(ret), K(str), K(length_str), K(i),
499
K(pattern), K(length_pat), K(j));
500
} else if (OB_FAIL(check_stack_overflow(is_stack_overflow))) {
501
LOG_WARN("check stack overflow failed", K(ret));
502
} else if (is_stack_overflow) {
503
ret = OB_SIZE_OVERFLOW;
504
LOG_WARN("too deep recursive", K(ret));
505
} else if (i == length_str && j == length_pat) {
507
} else if (i != length_str && j >= length_pat) {
509
} else if (j < length_pat && pattern[j] == '%') {
511
if (OB_FAIL(like_match(str, length_str, i,
512
pattern, length_pat, j,
514
LOG_WARN("failed to match", K(ret));
515
} else if (!is_match && i < length_str) {
518
if (OB_FAIL(like_match(str, length_str, i,
519
pattern, length_pat, j,
521
LOG_WARN("failed to match", K(ret));
524
} else if (i < length_str && j < length_pat && pattern[j] == '_') {
527
if (OB_FAIL(like_match(str, length_str, i,
528
pattern, length_pat, j,
530
LOG_WARN("failed to match", K(ret));
532
} else if (i < length_str && j < length_pat && tolower(str[i]) == tolower(pattern[j])) {
535
if (OB_FAIL(like_match(str, length_str, i,
536
pattern, length_pat, j,
538
LOG_WARN("failed to match", K(ret));
546
int ObQueryDriver::convert_lob_locator_to_longtext(ObObj& value, sql::ObResultSet &result)
548
int ret = OB_SUCCESS;
549
ObArenaAllocator *allocator = NULL;
550
if (OB_FAIL(result.get_exec_context().get_convert_charset_allocator(allocator))) {
551
LOG_WARN("fail to get lob fake allocator", K(ret));
552
} else if (OB_ISNULL(allocator)) {
553
ret = OB_ERR_UNEXPECTED;
554
LOG_WARN("lob fake allocator is null.", K(ret), K(value));
555
} else if (OB_FAIL(convert_lob_locator_to_longtext(value,
556
session_.is_client_use_lob_locator(),
558
LOG_WARN("convert lob to longtext fail.", K(ret), K(value));
563
int ObQueryDriver::convert_lob_locator_to_longtext(ObObj& value,
564
bool is_use_lob_locator,
565
ObIAllocator *allocator)
567
int ret = OB_SUCCESS;
568
// 如果客户端使用新的lob locator, 则返回lob locator数据
569
// 如果客户端使用老的lob(没有locator头, 仅数据), 则返回老的lob
570
if (lib::is_oracle_mode()) {
571
if (is_use_lob_locator && value.is_lob()) {
574
ObLobLocator *lob_locator = nullptr;
575
if (OB_FAIL(value.get_string(str))) {
576
STORAGE_LOG(WARN, "Failed to get string from obj", K(ret), K(value));
577
} else if (OB_ISNULL(buf = static_cast<char*>(
578
allocator->alloc(str.length() + sizeof(ObLobLocator))))) {
579
ret = OB_ALLOCATE_MEMORY_FAILED;
580
LOG_WARN("Failed to allocate memory for lob locator", K(ret), K(str));
581
} else if (FALSE_IT(lob_locator = reinterpret_cast<ObLobLocator *> (buf))) {
582
} else if (OB_FAIL(lob_locator->init(str))) {
583
STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(str), KPC(lob_locator));
585
value.set_lob_locator(*lob_locator);
586
LOG_TRACE("return lob locator", K(*lob_locator), K(str));
588
} else if (!is_use_lob_locator && value.is_lob_locator()) {
590
if (OB_ISNULL(value.get_lob_locator())) {
591
ret = OB_INVALID_ARGUMENT;
592
LOG_WARN("invalid argument", K(value));
593
} else if (OB_FAIL(value.get_lob_locator()->get_payload(payload))) {
594
LOG_WARN("fail to get payload", K(ret));
596
value.set_lob_value(ObLongTextType,
598
static_cast<int32_t>(payload.length()));
601
LOG_TRACE("return data", K(is_use_lob_locator), K(value), K(lbt()));
606
int ObQueryDriver::process_lob_locator_results(ObObj& value, sql::ObResultSet &result)
608
int ret = OB_SUCCESS;
609
ObArenaAllocator *allocator = NULL;
610
if (OB_FAIL(result.get_exec_context().get_convert_charset_allocator(allocator))) {
611
LOG_WARN("fail to get lob fake allocator", K(ret));
612
} else if (OB_ISNULL(allocator)) {
613
ret = OB_ERR_UNEXPECTED;
614
LOG_WARN("lob fake allocator is null.", K(ret), K(value));
615
} else if (OB_FAIL(process_lob_locator_results(value,
616
session_.is_client_use_lob_locator(),
617
session_.is_client_support_lob_locatorv2(),
619
&result.get_session()))) {
620
LOG_WARN("convert lob to longtext fail.", K(ret), K(value));
625
int ObQueryDriver::process_lob_locator_results(ObObj& value,
626
bool is_use_lob_locator,
627
bool is_support_outrow_locator_v2,
628
ObIAllocator *allocator,
629
const sql::ObSQLSessionInfo *session_info)
631
int ret = OB_SUCCESS;
632
// 1. if client is_use_lob_locator, return lob locator
633
// 2. if client is_use_lob_locator, but not support outrow lob, return lob locator with inrow data
634
// refer to sz/aibo1m
635
// 3. if client does not support use_lob_locator ,,return full lob data without locator header
636
bool is_lob_type = value.is_lob() || value.is_json() || value.is_geometry() || value.is_lob_locator();
637
bool is_actual_return_lob_locator = is_use_lob_locator && !value.is_json();
639
// not lob types, do nothing
640
} else if (value.is_null() || value.is_nop_value()) {
642
} else if (is_actual_return_lob_locator && is_lob_type && lib::is_oracle_mode()) {
643
// Should be ObLobType (cluster version < 4.1), or Text/Json/Gis with lob header
644
ObLobLocatorV2 loc(value.get_string(), value.has_lob_header());
645
if (loc.is_lob_locator_v1()) {// do nothing, lob locator version 1
646
} else if (loc.is_valid()) { // lob locator v2
647
if (!loc.has_lob_header()) {
648
ObString data = value.get_string();
649
ObTextStringResult new_tmp_lob(value.get_type(), true, allocator);
650
if (OB_FAIL(new_tmp_lob.init(data.length()))) {
651
LOG_WARN("fail to init text string result", K(ret), K(new_tmp_lob), K(data.length()));
652
} else if (OB_FAIL(new_tmp_lob.append(data))) {
653
LOG_WARN("fail to append data", K(ret), K(new_tmp_lob), K(data.length()));
656
new_tmp_lob.get_result_buffer(res);
657
value.set_lob_value(value.get_type(), res.ptr(), res.length());
658
value.set_has_lob_header(); // must has lob header
660
} else if (!loc.has_extern()) {
661
if (!loc.has_inrow_data()) {
662
// currently all temp lobs have extern field in oracle mode
663
// or the lob locator header cannot compatable with clients for 4.0
664
ret = OB_INVALID_ARGUMENT;
665
LOG_WARN("Lob: oracle lob locator v2 with out extern segment", K(value), K(GET_MIN_CLUSTER_VERSION()));
666
} else if (!is_support_outrow_locator_v2) {
667
// convert to full extern temp lob locator
669
if (OB_FAIL(loc.get_inrow_data(inrow_data))) {
670
LOG_WARN("Lob: get inrow data failed", K(ret), K(loc));
672
value.set_string(value.get_type(), inrow_data.ptr(), inrow_data.length());
674
if (OB_FAIL(ObTextStringResult::ob_convert_obj_temporay_lob(value, *allocator))) {
675
LOG_WARN("fail to convert temp lob locator", K(ret), K(value));
680
if (!is_support_outrow_locator_v2 && !loc.has_inrow_data()) {
681
if (OB_FAIL(ObTextStringIter::append_outrow_lob_fulldata(value, session_info, *allocator))) {
682
LOG_WARN("Lob: convert lob to outrow failed", K(value), K(GET_MIN_CLUSTER_VERSION()));
687
ret = OB_INVALID_ARGUMENT;
688
LOG_WARN("Lob: invalid lob locator", K(value), K(GET_MIN_CLUSTER_VERSION()));
690
} else if ((!is_actual_return_lob_locator && lib::is_oracle_mode())
691
|| lib::is_mysql_mode()) {
692
// Should remove locator header and read full lob data
694
ObLobLocatorV2 loc(value.get_string(), value.has_lob_header());
695
if (loc.is_null()) { // maybe v1 empty lob
696
} else if (loc.is_lob_locator_v1()) {
697
if (OB_FAIL(convert_lob_locator_to_longtext(value, is_use_lob_locator, allocator))) {
698
LOG_WARN("Lob: handle lob locator v1 failed", K(value), K(GET_MIN_CLUSTER_VERSION()));
700
} else { // lob locator v2
701
ObArenaAllocator tmp_alloc("ObLobRead", OB_MALLOC_NORMAL_BLOCK_SIZE, session_info->get_effective_tenant_id());
702
ObTextStringIter instr_iter(value);
703
if (OB_FAIL(instr_iter.init(0, session_info, allocator, &tmp_alloc))) {
704
LOG_WARN("init lob str inter failed", K(ret), K(value));
705
} else if (OB_FAIL(instr_iter.get_full_data(data))) {
706
LOG_WARN("Lob: init lob str iter failed ", K(value));
708
ObObjType dst_type = ObLongTextType;
709
if (value.is_json()) {
710
dst_type = ObJsonType;
711
} else if (value.is_geometry()) {
712
dst_type = ObGeometryType;
714
// remove has lob header flag
715
value.set_lob_value(dst_type, data.ptr(), static_cast<int32_t>(data.length()));
718
} else { /* do nothing */ }
722
int ObQueryDriver::convert_string_charset(const ObString &in_str, const ObCollationType in_cs_type,
723
const ObCollationType out_cs_type,
724
char *buf, int32_t buf_len, uint32_t &result_len)
726
int ret = OB_SUCCESS;
727
ret = ObCharset::charset_convert(in_cs_type, in_str.ptr(),
728
in_str.length(),out_cs_type, buf, buf_len, result_len);
729
if (OB_SUCCESS != ret) {
730
int32_t str_offset = 0;
731
int64_t buf_offset = 0;
732
ObString question_mark = ObCharsetUtils::get_const_str(out_cs_type, '?');
733
while (str_offset < in_str.length() && buf_offset + question_mark.length() <= buf_len) {
734
int64_t offset = ObCharset::charpos(in_cs_type, in_str.ptr() + str_offset,
735
in_str.length() - str_offset, 1);
736
ret = ObCharset::charset_convert(in_cs_type, in_str.ptr() + str_offset, offset, out_cs_type,
737
buf + buf_offset, buf_len - buf_offset, result_len);
738
str_offset += offset;
739
if (OB_SUCCESS == ret) {
740
buf_offset += result_len;
742
MEMCPY(buf + buf_offset, question_mark.ptr(), question_mark.length());
743
buf_offset += question_mark.length();
746
if (str_offset < in_str.length()) {
747
ret = OB_SIZE_OVERFLOW;
748
LOG_WARN("sizeoverflow", K(ret), K(in_str), KPHEX(in_str.ptr(), in_str.length()));
750
result_len = buf_offset;
752
LOG_WARN("charset convert failed", K(ret), K(in_cs_type), K(out_cs_type));
758
int ObQueryDriver::convert_lob_value_charset(ObObj& value,
759
ObCharsetType charset_type,
760
ObIAllocator &allocator)
762
int ret = OB_SUCCESS;
765
ObLobLocator *lob_locator = NULL;
766
if (OB_FAIL(value.get_lob_locator(lob_locator))) {
767
LOG_WARN("get lob locator failed", K(ret));
768
} else if (OB_ISNULL(lob_locator)) {
769
ret = OB_ERR_UNEXPECTED;
770
LOG_WARN("get null lob locator", K(ret));
771
} else if (OB_FAIL(lob_locator->get_payload(str))) {
772
LOG_WARN("get lob locator payload failed", K(ret));
773
} else if (ObCharset::is_valid_charset(charset_type) && CHARSET_BINARY != charset_type) {
774
ObCollationType collation_type = ObCharset::get_default_collation(charset_type);
775
const ObCharsetInfo *from_charset_info = ObCharset::get_charset(value.get_collation_type());
776
const ObCharsetInfo *to_charset_info = ObCharset::get_charset(collation_type);
777
if (OB_ISNULL(from_charset_info) || OB_ISNULL(to_charset_info)) {
778
ret = OB_ERR_UNEXPECTED;
779
LOG_WARN("charsetinfo is null", K(ret), K(value.get_collation_type()), K(collation_type));
780
} else if (CS_TYPE_INVALID == value.get_collation_type() || CS_TYPE_INVALID == collation_type) {
781
ret = OB_ERR_UNEXPECTED;
782
LOG_WARN("invalid collation", K(value.get_collation_type()), K(collation_type), K(ret));
783
} else if (CS_TYPE_BINARY != value.get_collation_type() && CS_TYPE_BINARY != collation_type
784
&& strcmp(from_charset_info->csname, to_charset_info->csname) != 0) {
786
int32_t header_len = value.get_val_len() - lob_locator->payload_size_;
787
int32_t str_len = lob_locator->payload_size_ * 4;
788
uint32_t result_len = 0;
789
if (OB_UNLIKELY(NULL == (buf = static_cast<char *>(
790
allocator.alloc(header_len + str_len))))) {
791
ret = OB_ALLOCATE_MEMORY_FAILED;
792
LOG_ERROR("alloc memory failed", K(ret), K(header_len), K(str_len));
794
MEMCPY(buf, lob_locator, header_len);
795
if (OB_FAIL(convert_string_charset(str, value.get_collation_type(), collation_type,
796
buf + header_len, str_len, result_len))) {
797
LOG_WARN("convert string charset failed", K(ret));
799
ObLobLocator *result_lob = reinterpret_cast<ObLobLocator *>(buf);
800
result_lob->payload_size_ = result_len;
801
value.set_lob_locator(*result_lob);
802
value.set_collation_type(collation_type);
810
int ObQueryDriver::convert_text_value_charset(ObObj& value,
811
ObCharsetType charset_type,
812
ObIAllocator &allocator,
813
const sql::ObSQLSessionInfo *session)
815
int ret = OB_SUCCESS;
816
ObString raw_str = value.get_string();
817
if (value.is_null() || value.is_nop_value()) {
818
} else if (OB_ISNULL(raw_str.ptr()) || raw_str.length() == 0) {
819
if (!value.has_lob_header() || !value.is_lob_storage()) {
820
LOG_DEBUG("Lob: get empty or null obj without header or not lob", K(value));
822
ret = OB_ERR_UNEXPECTED;
823
LOG_WARN("Lob: get empty or null lob obj with header", K(ret), K(value));
825
} else if (ObCharset::is_valid_charset(charset_type) && CHARSET_BINARY != charset_type) {
826
ObCollationType to_collation_type = ObCharset::get_default_collation(charset_type);
827
ObCollationType from_collation_type = value.get_collation_type();
828
const ObCharsetInfo *from_charset_info = ObCharset::get_charset(from_collation_type);
829
const ObCharsetInfo *to_charset_info = ObCharset::get_charset(to_collation_type);
830
const ObObjType type = value.get_type();
832
if (OB_ISNULL(from_charset_info) || OB_ISNULL(to_charset_info)) {
833
ret = OB_ERR_UNEXPECTED;
834
LOG_WARN("Lob: charsetinfo is null", K(ret), K(from_collation_type), K(to_collation_type));
835
} else if (CS_TYPE_INVALID == from_collation_type || CS_TYPE_INVALID == to_collation_type) {
836
ret = OB_ERR_UNEXPECTED;
837
LOG_WARN("Lob: invalid collation", K(from_collation_type), K(to_collation_type), K(ret));
838
} else if (CS_TYPE_BINARY != from_collation_type && CS_TYPE_BINARY != to_collation_type
839
&& strcmp(from_charset_info->csname, to_charset_info->csname) != 0) {
840
bool is_actual_return_lob_locator = session->is_client_use_lob_locator() && !value.is_json();
841
if (value.is_lob_storage() && value.has_lob_header() && OB_NOT_NULL(session) &&
842
is_actual_return_lob_locator && lib::is_oracle_mode()) {
845
if (OB_FAIL(process_lob_locator_results(value,
846
session->is_client_use_lob_locator(),
847
session->is_client_support_lob_locatorv2(),
850
LOG_WARN("fail to process lob locator", K(ret), K(value));
851
} else if (OB_FAIL(value.get_lob_locatorv2(lob))) {
852
LOG_WARN("fail to lob locator v2", K(ret), K(value));
853
} else if (!lob.has_inrow_data()) {
855
} else if (OB_FAIL(lob.get_inrow_data(inrow_data))) {
856
LOG_WARN("fail to get inrow data", K(ret), K(lob));
857
} else if (inrow_data.length() == 0) {
860
int64_t lob_data_byte_len = inrow_data.length();
861
int64_t offset_len = reinterpret_cast<uint64_t>(inrow_data.ptr()) - reinterpret_cast<uint64_t>(lob.ptr_);
862
int64_t res_len = offset_len + lob_data_byte_len * ObCharset::CharConvertFactorNum;
863
char *buf = static_cast<char*>(allocator.alloc(res_len));
864
if (OB_ISNULL(buf)) {
865
ret = OB_ALLOCATE_MEMORY_FAILED;
866
LOG_WARN("fail to alloc memory", K(ret), K(res_len));
868
MEMCPY(buf, lob.ptr_, offset_len);
869
uint32_t result_len = 0;
870
if (OB_FAIL(convert_string_charset(inrow_data, from_collation_type, to_collation_type,
871
buf + offset_len, res_len - offset_len, result_len))) {
872
LOG_WARN("Lob: convert string charset failed", K(ret));
874
lob.assign_buffer(buf, offset_len + result_len, lob.has_lob_header());
875
// refresh payload size
876
if (lob.has_extern()) {
877
ObMemLobExternHeader *ex_header = nullptr;
878
if (OB_FAIL(lob.get_extern_header(ex_header))) {
879
LOG_WARN("fail to get extern header", K(ret), K(lob));
881
ex_header->payload_size_ = result_len;
884
// refresh lob data size
886
ObLobCommon *lob_common = nullptr;
887
if (OB_FAIL(lob.get_disk_locator(lob_common))) {
888
LOG_WARN("fail to get lob common", K(ret), K(lob));
889
} else if (lob_common->is_init_) {
890
ObLobData *lob_data = reinterpret_cast<ObLobData*>(lob_common->buffer_);
891
lob_data->byte_size_ = result_len;
895
LOG_DEBUG("Lob: new temp convert_text_value_charset in convert_text_value",
896
K(ret), K(raw_str), K(type), K(to_collation_type), K(from_collation_type),
897
K(from_charset_info->csname), K(to_charset_info->csname));
898
value.set_lob_value(type, buf, offset_len + result_len);
899
value.set_collation_type(to_collation_type);
900
value.set_has_lob_header();
906
// get full data, buffer size is full byte length * ObCharset::CharConvertFactorNum
907
ObString data_str = value.get_string();
908
int64_t lob_data_byte_len = data_str.length();
909
if (!value.has_lob_header()) {
911
ObLobLocatorV2 loc(raw_str, value.has_lob_header());
912
ObTextStringIter str_iter(value);
913
if (OB_FAIL(str_iter.init(0, session, &allocator))) {
914
LOG_WARN("Lob: init lob str iter failed ", K(ret), K(value));
915
} else if (OB_FAIL(str_iter.get_full_data(data_str))) {
916
LOG_WARN("Lob: get full data failed ", K(ret), K(value));
917
} else if (OB_FAIL(loc.get_lob_data_byte_len(lob_data_byte_len))) {
918
LOG_WARN("Lob: get lob data byte len failed", K(ret), K(loc));
922
// mock result buffer and reserve data length
923
// could do streaming charset convert
924
ObTextStringResult new_tmp_lob(type, value.has_lob_header(), &allocator);
927
uint32_t result_len = 0;
928
int64_t converted_len = lob_data_byte_len * ObCharset::CharConvertFactorNum;
929
if (OB_FAIL(new_tmp_lob.init(converted_len))) {
930
LOG_WARN("Lob: init tmp lob failed", K(ret), K(converted_len));
931
} else if (OB_FAIL(new_tmp_lob.get_reserved_buffer(buf, buf_len))) {
932
LOG_WARN("Lob: get empty buffer failed", K(ret), K(converted_len));
933
} else if (OB_FAIL(convert_string_charset(data_str, from_collation_type, to_collation_type,
934
buf, buf_len, result_len))) {
935
LOG_WARN("Lob: convert string charset failed", K(ret));
936
} else if (OB_FAIL(new_tmp_lob.lseek(result_len, 0))) {
937
LOG_WARN("Lob: temp lob lseek failed", K(ret));
939
ObString lob_loc_str;
940
new_tmp_lob.get_result_buffer(lob_loc_str);
941
LOG_DEBUG("Lob: new temp convert_text_value_charset in convert_text_value",
942
K(ret), K(raw_str), K(type), K(to_collation_type), K(from_collation_type),
943
K(from_charset_info->csname), K(to_charset_info->csname));
944
value.set_lob_value(type, lob_loc_str.ptr(), lob_loc_str.length());
945
value.set_collation_type(to_collation_type);
946
if (new_tmp_lob.has_lob_header()) {
947
value.set_has_lob_header();
957
/*@brief:is_com_filed_list_match_wildcard_str 用于匹配client发过来的COM_FIELD_LIST中包含的参数中有匹配符
958
* 情形,eg:COM_FIELD_LIST(t1, c*) , t1 中有c1,c2,pk 三列 ==> 仅返回c1, c2,不返回 pk,因为他和 c* 不匹配;
959
* 其规则类似于like情形;详细参考链接:
962
int ObQueryDriver::is_com_filed_list_match_wildcard_str(ObResultSet &result,
963
const ObCollationType &from_collation,
964
const ObString &from_string,
967
int ret = OB_SUCCESS;
968
is_not_match = false;
969
if (!result.get_is_com_filed_list() || result.get_wildcard_string().empty()) {
972
/*需要考虑不同的字符集之间进行比较时需要转换为同一种字符集进行比较*/
973
ObIAllocator &allocator = result.get_mem_pool();
974
ObString wildcard_str;
975
if (result.get_session().get_nls_collation() != from_collation) {
976
if (OB_FAIL(convert_field_charset(allocator,
977
result.get_session().get_nls_collation(),
979
result.get_wildcard_string(),
981
LOG_WARN("failed to convert field charset", K(ret));
984
wildcard_str = result.get_wildcard_string();
987
bool is_match = false;
988
if (OB_FAIL(like_match(from_string.ptr(),
989
from_string.length(),
992
wildcard_str.length(),
995
LOG_WARN("failed to like match", K(ret));
996
} else if (!is_match) {