oceanbase

Форк
0
/
ob_query_driver.cpp 
1005 строк · 44.4 Кб
1
/**
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.
11
 */
12

13
#define USING_LOG_PREFIX SERVER
14

15
#include "ob_query_driver.h"
16
#include "ob_mysql_result_set.h"
17
#include "obmp_base.h"
18
#include "obsm_row.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"
23
#include <string.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"
31
#endif
32

33
namespace oceanbase
34
{
35
using namespace common;
36
using namespace sql;
37
using namespace obmysql;
38
namespace observer
39
{
40

41
int ObQueryDriver::response_query_header(ObResultSet &result,
42
                                         bool has_more_result,
43
                                         bool need_set_ps_out_flag,
44
                                         bool need_flush_buffer)
45
{
46
  int ret = OB_SUCCESS;
47
  if (is_prexecute_) {
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));
51
    }
52
  } else {
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(),
57
                                             has_more_result,
58
                                             need_set_ps_out_flag,
59
                                             false,
60
                                             &result))) {
61
      LOG_WARN("response query head fail. ", K(ret));
62
    }
63
  }
64
  if (OB_FAIL(ret)) {
65
    result.set_errcode(ret);
66
  }
67
  return ret;
68
}
69

70
int ObQueryDriver::response_query_header(const ColumnsFieldIArray &fields,
71
                                         bool has_more_result,
72
                                         bool need_set_ps_out_flag,
73
                                         bool ps_cursor_execute,
74
                                         ObResultSet *result)
75
{
76
  int ret = OB_SUCCESS;
77
  bool ac = true;
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())) {
88
    // 普通协议发送 cnt 值
89
    OMPKResheader rhp;
90
    rhp.set_field_count(fields.count());
91
    if (OB_FAIL(sender_.response_packet(rhp, &session_))) {
92
      LOG_WARN("response packet fail", K(ret));
93
    }
94
  } else {
95
    // com field 协议在这里什么都不发,直接发送 field 信息
96
  }
97

98
  // 发送 field 信息
99
  if (OB_SUCC(ret)) {
100
    for (int64_t i = 0; OB_SUCC(ret) && i < fields.count(); ++i) {
101
      bool is_not_match = false;
102
      ObMySQLField field;
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(
106
                                                  *result,
107
                                                  static_cast<ObCollationType>(ob_field.charsetnr_),
108
                                                  ob_field.org_cname_,
109
                                                  is_not_match))) {
110
        LOG_WARN("failed to is com filed list match wildcard str", K(ret));
111
      } else if (is_not_match) {
112
        /*do nothing*/
113
      } else {
114
        ret = ObMySQLResultSet::to_mysql_field(ob_field, field);
115
        if (OB_SUCC(ret)) {
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());
119
          }
120
          OMPKField fp(field);
121
          if (OB_FAIL(sender_.response_packet(fp, &session_))) {
122
            LOG_WARN("response packet fail", K(ret));
123
          }
124
        }
125
      }
126
    }
127
  }
128

129
  if (OB_SUCC(ret)) {
130
    OMPKEOF eofp;
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();
143
    }
144
    eofp.set_server_status(flags);
145

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));
151
      } else {
152
        // in multi-stmt, send extra ok packet in the last stmt(has no more result)
153
        ObOKPParam ok_param;
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));
159
        }
160
      }
161
    } else {
162
      if (OB_FAIL(sender_.response_packet(eofp, &session_))) {
163
        LOG_WARN("response packet fail", K(ret));
164
      }
165
    }
166
  }
167
  return ret;
168
}
169

170
int ObQueryDriver::response_query_result(ObResultSet &result,
171
                                         bool is_ps_protocol,
172
                                         bool has_more_result,
173
                                         bool &can_retry,
174
                                         int64_t fetch_limit)
175
{
176
  int ret = OB_SUCCESS;
177
  FLTSpanGuard(response_result);
178
  can_retry = true;
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;
184
  int64_t row_num = 0;
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));
191
      }
192
    }
193
  }
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;
197
  if (OB_SUCC(ret)) {
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));
202
    }
203
  }
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));
208
      break;
209
    }
210
    // 如果是第一行,则先给客户端回复field等信息
211
    if (is_first_row) {
212
      is_first_row = false;
213
      can_retry = false; // 已经获取到第一行数据,不再重试了
214
#ifdef OB_BUILD_SPM
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);
219
      }
220
#endif
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));
223
      }
224
    }
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(),
232
                                           cast_ctx,
233
                                           value,
234
                                           value))) {
235
            LOG_WARN("failed to cast object", K(ret), K(value),
236
                     K(value.get_type()), K(fields->at(i).type_.get_type()));
237
          }
238
        }
239
      }
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
247
        //    remove locator
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));
257
        }
258
        if (OB_FAIL(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()));
265
#endif
266
        }
267
      }
268
    }
269
    if (OB_SUCC(ret)) {
270
      const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(&session_);
271
      ObSMRow sm(protocol_type, *row, dtc_params,
272
                         result.get_field_columns(),
273
                         ctx_.schema_guard_,
274
                         session_.get_effective_tenant_id());
275
      sm.set_packed(is_packed);
276
      OMPKRow rp(sm);
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),
280
            K(can_retry));
281
        // break;
282
      } else {
283
        LOG_DEBUG("response row succ", K(*row));
284
      }
285
      if (OB_SUCC(ret)) {
286
        ++row_num;
287
        if (0 == row_num % RESET_CONVERT_CHARSET_ALLOCATOR_EVERY_X_ROWS) {
288
          (void) result.get_exec_context().try_reset_convert_charset_allocator();
289
        }
290
      }
291
    }
292
  }
293
  if (is_cac_found_rows) {
294
    while (OB_SUCC(ret) && !OB_FAIL(result.get_next_row(result_row))) {
295
      // nothing
296
    }
297
  }
298
  if (OB_ITER_END == ret) {
299
    ret = OB_SUCCESS;
300
  } else {
301
    LOG_WARN("fail to iterate and response", K(ret), K(row_num), K(can_retry));
302
  }
303
  if (OB_SUCC(ret) && 0 == row_num) {
304
    // 如果是一行数据也没有,则还是要给客户端回复field等信息,并且不再重试了
305
    can_retry = false;
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));
308
    }
309
  }
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));
312
  }
313

314
  return ret;
315
}
316

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)
322
{
323
  int ret = OB_SUCCESS;
324
  char *buf = NULL;
325
  int32_t buf_len = from_string.length() * ObCharset::CharConvertFactorNum;
326
  uint32_t result_len = 0;
327
  if (0 == buf_len) {
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),
334
          from_string.ptr(),
335
          from_string.length(),
336
          dest_collation,
337
          buf,
338
          buf_len,
339
          result_len))) {
340
    LOG_WARN("charset convert failed", K(ret), K(from_collation), K(dest_collation));
341
  } else {
342
    dest_string.assign(buf, static_cast<int32_t>(result_len));
343
  }
344
  return ret;
345
}
346

347
int ObQueryDriver::convert_string_value_charset(ObObj& value, ObResultSet &result)
348
{
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));
366
  } else {
367
    to_collation_type = ObCharset::get_default_collation(charset_type);
368
  }
369
  if (OB_FAIL(ret)) {
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));
378
    }
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));
384
  } else {
385
    OZ (value.convert_string_value_charset(charset_type, *allocator));
386
  }
387
  return ret;
388
}
389

390
int ObQueryDriver::convert_string_value_charset(ObObj& value, 
391
                                                ObCharsetType charset_type, 
392
                                                ObIAllocator &allocator)
393
{
394
  int ret = OB_SUCCESS;
395
  ObString str;
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) {
409
      char *buf = NULL;
410
      int32_t buf_len = str.length() * ObCharset::CharConvertFactorNum;
411
      uint32_t result_len = 0;
412
      if (0 == buf_len) {
413
        //do noting
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));
421
      } else {
422
        value.set_string(value.get_type(), buf, static_cast<int32_t>(result_len));
423
        value.set_collation_type(collation_type);
424
      }
425
    }
426
  }
427
  return ret;
428
}
429

430
int ObQueryDriver::convert_lob_value_charset(common::ObObj& value, sql::ObResultSet &result)
431
{
432
  int ret = OB_SUCCESS;
433

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;
452
  }
453
  if (OB_FAIL(ret)) {
454
  } else if (OB_FAIL(convert_lob_value_charset(value, charset_type, *allocator))) {
455
    LOG_WARN("convert lob value fail.", K(ret), K(value));
456
  }
457
  return ret;
458
}
459

460
int ObQueryDriver::convert_text_value_charset(common::ObObj& value, sql::ObResultSet &result)
461
{
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;
481
  }
482
  if (OB_FAIL(ret)) {
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));
485
  }
486
  return ret;
487
}
488

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,
491
                              bool &is_match)
492
{
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) {
506
    is_match = true;
507
  } else if (i != length_str && j >= length_pat) {
508
    is_match = false;
509
  } else if (j < length_pat && pattern[j] == '%') {
510
    ++j;
511
    if (OB_FAIL(like_match(str, length_str, i,
512
                           pattern, length_pat, j,
513
                           is_match))) {
514
      LOG_WARN("failed to match", K(ret));
515
    } else if (!is_match && i < length_str) {
516
      ++i;
517
      --j;
518
      if (OB_FAIL(like_match(str, length_str, i,
519
                             pattern, length_pat, j,
520
                             is_match))) {
521
        LOG_WARN("failed to match", K(ret));
522
      }
523
    }
524
  } else if (i < length_str && j < length_pat && pattern[j] == '_') {
525
    ++i;
526
    ++j;
527
    if (OB_FAIL(like_match(str, length_str, i,
528
                           pattern, length_pat, j,
529
                           is_match))) {
530
      LOG_WARN("failed to match", K(ret));
531
    }
532
  } else if (i < length_str && j < length_pat && tolower(str[i]) == tolower(pattern[j])) {
533
    ++i;
534
    ++j;
535
    if (OB_FAIL(like_match(str, length_str, i,
536
                           pattern, length_pat, j,
537
                           is_match))) {
538
      LOG_WARN("failed to match", K(ret));
539
    }
540
  } else {
541
    is_match = false;
542
  }
543
  return ret;
544
}
545

546
int ObQueryDriver::convert_lob_locator_to_longtext(ObObj& value, sql::ObResultSet &result)
547
{
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(), 
557
                                                     allocator))) {
558
    LOG_WARN("convert lob to longtext fail.", K(ret), K(value));
559
  }
560
  return ret;
561
}
562

563
int ObQueryDriver::convert_lob_locator_to_longtext(ObObj& value,
564
                                                   bool is_use_lob_locator,
565
                                                   ObIAllocator *allocator)
566
{
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()) {
572
      ObString str;
573
      char *buf = nullptr;
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));
584
      } else {
585
        value.set_lob_locator(*lob_locator);
586
        LOG_TRACE("return lob locator", K(*lob_locator), K(str));
587
      }
588
    } else if (!is_use_lob_locator && value.is_lob_locator()) {
589
      ObString payload;
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));
595
      } else {
596
        value.set_lob_value(ObLongTextType,
597
                            payload.ptr(),
598
                            static_cast<int32_t>(payload.length()));
599
      }
600
    }
601
    LOG_TRACE("return data", K(is_use_lob_locator), K(value), K(lbt()));
602
  }
603
  return ret;
604
}
605

606
int ObQueryDriver::process_lob_locator_results(ObObj& value, sql::ObResultSet &result)
607
{
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(),
618
                                                 allocator,
619
                                                 &result.get_session()))) {
620
    LOG_WARN("convert lob to longtext fail.", K(ret), K(value));
621
  }
622
  return ret;
623
}
624

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)
630
{
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();
638
  if (!is_lob_type) {
639
    // not lob types, do nothing
640
  } else if (value.is_null() || value.is_nop_value()) {
641
    // do nothing
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()));
654
        } else {
655
          ObString res;
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
659
        }
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
668
          ObString inrow_data;
669
          if (OB_FAIL(loc.get_inrow_data(inrow_data))) {
670
            LOG_WARN("Lob: get inrow data failed", K(ret), K(loc));
671
          } else {
672
            value.set_string(value.get_type(), inrow_data.ptr(), inrow_data.length());
673
            value.set_inrow();
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));
676
            }
677
          }
678
        }
679
      } else {
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()));
683
          }
684
        }
685
      }
686
    } else {
687
      ret = OB_INVALID_ARGUMENT;
688
      LOG_WARN("Lob: invalid lob locator", K(value), K(GET_MIN_CLUSTER_VERSION()));
689
    }
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
693
    ObString 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()));
699
      }
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));
707
      } else {
708
        ObObjType dst_type = ObLongTextType;
709
        if (value.is_json()) {
710
          dst_type = ObJsonType;
711
        } else if (value.is_geometry()) {
712
          dst_type = ObGeometryType;
713
        }
714
        // remove has lob header flag
715
        value.set_lob_value(dst_type, data.ptr(), static_cast<int32_t>(data.length()));
716
      }
717
    }
718
  } else { /* do nothing */ }
719
  return ret;
720
}
721

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)
725
{
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;
741
      } else {
742
        MEMCPY(buf + buf_offset, question_mark.ptr(), question_mark.length());
743
        buf_offset += question_mark.length();
744
      }
745
    }
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()));
749
    } else {
750
      result_len = buf_offset;
751
      ret = OB_SUCCESS;
752
      LOG_WARN("charset convert failed", K(ret), K(in_cs_type), K(out_cs_type));
753
    }
754
  }
755
  return ret;
756
}
757

758
int ObQueryDriver::convert_lob_value_charset(ObObj& value,
759
                                             ObCharsetType charset_type, 
760
                                             ObIAllocator &allocator)
761
{
762
  int ret = OB_SUCCESS;
763

764
  ObString str;
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) {
785
      char *buf = NULL;
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));
793
      } else {
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));
798
        } else {
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);
803
        }
804
      }
805
    }
806
  }
807
  return ret;
808
}
809

810
int ObQueryDriver::convert_text_value_charset(ObObj& value,
811
                                              ObCharsetType charset_type,
812
                                              ObIAllocator &allocator,
813
                                              const sql::ObSQLSessionInfo *session)
814
{
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));
821
    } else {
822
      ret = OB_ERR_UNEXPECTED;
823
      LOG_WARN("Lob: get  empty or null lob obj with header", K(ret), K(value));
824
    }
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();
831

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()) {
843
        ObLobLocatorV2 lob;
844
        ObString inrow_data;
845
        if (OB_FAIL(process_lob_locator_results(value,
846
                                                session->is_client_use_lob_locator(),
847
                                                session->is_client_support_lob_locatorv2(),
848
                                                &allocator,
849
                                                session))) {
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()) {
854
          // do nothing
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) {
858
          // do nothing
859
        } else {
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));
867
          } else {
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));
873
            } else {
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));
880
                } else {
881
                  ex_header->payload_size_ = result_len;
882
                }
883
              }
884
              // refresh lob data size
885
              if (OB_SUCC(ret)) {
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;
892
                }
893
              }
894
              if (OB_SUCC(ret)) {
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();
901
              }
902
            }
903
          }
904
        }
905
      } else {
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()) {
910
        } else {
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));
919
          }
920
        }
921
        if (OB_SUCC(ret)) {
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);
925
          char *buf = NULL;
926
          int64_t buf_len = 0;
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));
938
          } else {
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();
948
            }
949
          }
950
        }
951
      }
952
    }
953
  }
954
  return ret;
955
}
956

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情形;详细参考链接:
960
*
961
*/
962
int ObQueryDriver::is_com_filed_list_match_wildcard_str(ObResultSet &result,
963
                                                        const ObCollationType &from_collation,
964
                                                        const ObString &from_string,
965
                                                        bool &is_not_match)
966
{
967
  int ret = OB_SUCCESS;
968
  is_not_match = false;
969
  if (!result.get_is_com_filed_list() || result.get_wildcard_string().empty()) {
970
    /*do nothing*/
971
  } else {
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(),
978
                                        from_collation,
979
                                        result.get_wildcard_string(),
980
                                        wildcard_str))) {
981
        LOG_WARN("failed to convert field charset", K(ret));
982
      }
983
    } else {
984
      wildcard_str = result.get_wildcard_string();
985
    }
986
    if (OB_SUCC(ret)) {
987
      bool is_match = false;
988
      if (OB_FAIL(like_match(from_string.ptr(),
989
                             from_string.length(),
990
                             0,
991
                             wildcard_str.ptr(),
992
                             wildcard_str.length(),
993
                             0,
994
                             is_match))) {
995
        LOG_WARN("failed to like match", K(ret));
996
      } else if (!is_match) {
997
        is_not_match = true;
998
      }
999
    }
1000
  }
1001
  return ret;
1002
}
1003

1004
}
1005
}
1006

1007

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.