YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/bfql/bfql.h
Line
Count
Source (jump to first uncovered line)
1
//--------------------------------------------------------------------------------------------------
2
// Copyright (c) YugaByte, Inc.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
// in compliance with the License.  You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software distributed under the License
10
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
// or implied.  See the License for the specific language governing permissions and limitations
12
// under the License.
13
//
14
//
15
// This module defines the entries to the builtin library functions.
16
//   FindQLOpcode() - Compiling builtin call into opcode.
17
//   ExecQLOpcode() - Execute builtin call using opcode.
18
//
19
// NOTES ON BUILTIN DEFINITIONS
20
// ----------------------------
21
// Here's how new builtin functions are implemented or added to this library.
22
// * Define C++ function (e.g. Token) in this library or any C++ library (yb_bfql).
23
//   If the function is defined in a different library, link it to this library.
24
// * Define associated QL function ("token") by adding it to QL parser.
25
// * In file "directory.cc", add an entry at the end of the kBFDirectory table.
26
//     { C++ func_name , QL func_name , return_type, { formal_parameter_types } }
27
//     Example:
28
//     { "Token", "token", STRING, {TYPEARGS} }
29
// * The rest of the code would be auto-generated.
30
//
31
// NOTES ON PROCESSING BUILTIN CALLS
32
// ---------------------------------
33
// Here's how builtin calls can be processed using this library.
34
// - Getting the opcode from a process (such as client or proxy server).
35
//     FindQLOpcode(function_name,              // Input:         Such as "+"
36
//                   actual_parameter_types,     // Input:         Types of arguments.
37
//                   opcode,                     // Output:        Found associated opcode.
38
//                   formal_parameter_types,     // Output:        Types of formal parameters.
39
//                   return_type)                // Input/Output:  Return type.
40
// - Send the opcode & parameter values to any processes (such as tablet server).
41
// - The receiving process can then execute it.
42
//     ExecQLOpcode(opcode,                     // Input:         Opcode from compilation.
43
//                   param_values,               // Input:         Arguments.
44
//                   return_value)               // Output:        Computed result.
45
//
46
// NOTES ON COMPILING BUILTIN CALLS
47
// --------------------------------
48
// FindQLOpcode() should be called to type check a builtin calls.
49
// * FindQLOpcode() does type checking for the parameters (function signature).
50
// * FindQLOpcode() outputs a BFOpcode to be used at execution time.
51
// * FindQLOpcode() outputs the formal parameter types.
52
//   - This is the signature of the function.
53
//   - The arguments to a builtin call must be converted to these exact formal types.
54
// * FindQLOpcode() inputs / outputs the return type.
55
//   - If return type is not given (UNKNOWN_DATA), it returns the expected return type to caller.
56
//   - If return type is given, it checks if the type is compatible with the function's return type.
57
//
58
// NOTES ON EXECUTING BUILTIN CALLS
59
// --------------------------------
60
// Call ExecQLFunc(opcode, args, result)
61
// * Input arguments must be of exact datatypes as the formal parameter types. Operator "cast"
62
//   should have been used to convert these arguments when needed.
63
//
64
// * The return result must also be of expected type. The return value of expected type would be
65
//   written to this result.
66
//
67
// EXAMPPLE
68
// --------
69
// The test "/yb/util/bfql/bfql-test.cc" would be a good example on builtin-call usage.
70
// The file "/yb/yql/cql/ql/ptree/pt_bfunc.cc" can be used as example at the moment.
71
//--------------------------------------------------------------------------------------------------
72
73
#ifndef YB_BFQL_BFQL_H_
74
#define YB_BFQL_BFQL_H_
75
76
#include <vector>
77
#include <list>
78
79
#include "yb/util/logging.h"
80
#include "yb/bfql/bfql_template.h"
81
#include "yb/bfql/tserver_opcodes.h"
82
#include "yb/bfql/bfunc_names.h"
83
84
namespace yb {
85
namespace bfql {
86
87
//--------------------------------------------------------------------------------------------------
88
// class BFCompileApi<PType, RType> has one main entry function - FindQLOpcode().
89
//
90
// FindQLOpcode() finds the builtin opcode, signature, and return type using the function name.
91
// - This function is a template function which accept with any parameter and result classes that
92
//   implement the following functions.
93
//     DataType ql_type_id();
94
//     void set_ql_type_id(DataType);
95
//
96
// - Example
97
//   . QL expression treenode can be used for both PType and RType because it has the two required
98
//     functions for set & get ql_type_ids.
99
//   . Pseudo code.
100
//     using BFCompileQL = BFCompileApi<std::shared_ptr<QLValue>, QLValue>.
101
//
102
// - Example for a class that can be used as PType and Rtype for this template.
103
//     class YourArg {
104
//       DataType ql_type_id() { return ql_type_id_; }
105
//       void set_ql_type_id(DataType t) { ql_type_id_ = t; }
106
//     };
107
//
108
//   Builtin library provides interface for both raw and shared pointers.
109
//     vector<YourArgPointer> params = { ... };
110
//     BFCompileApi<YourArg, YourArg>::FindQLOpcode(name, params, opcode, decl, result_ptr);
111
112
template<typename PType, typename RType>
113
class BFCompileApi {
114
 public:
115
  //------------------------------------------------------------------------------------------------
116
  // Because we using Arena allocator, our compiler don't use standard collection types such as
117
  // std::vector. The following templates allow the compiler to resolve builtin calls with with
118
  // various collection types.
119
120
  // Interface for any collections of shared_ptrs.
121
  template<template<typename, typename> class CType, typename AType>
122
  static Status FindQLOpcodeImpl(const string& ql_name,
123
                                  const CType<std::shared_ptr<PType>, AType>& param_types,
124
                                  BFOpcode *opcode,
125
                                  const BFDecl **bfdecl,
126
1.07k
                                  const std::shared_ptr<RType>& result) {
127
1.07k
    Status s = FindOpcode<CType<std::shared_ptr<PType>, AType>, const std::shared_ptr<RType>&>(
128
1.07k
                   ql_name, param_types, opcode, bfdecl, result);
129
0
    VLOG(3) << "Compiled function call " << ql_name << ". Status: " << s.ToString();
130
1.07k
    return s;
131
1.07k
  }
_ZN2yb4bfql12BFCompileApiINS0_11BFTestValueES2_E16FindQLOpcodeImplINSt3__16vectorENS5_9allocatorINS5_10shared_ptrIS2_EEEEEENS_6StatusERKNS5_12basic_stringIcNS5_11char_traitsIcEENS7_IcEEEERKT_IS9_T0_EPNS0_8BFOpcodeEPPKNS0_6BFDeclERKS9_
Line
Count
Source
126
14
                                  const std::shared_ptr<RType>& result) {
127
14
    Status s = FindOpcode<CType<std::shared_ptr<PType>, AType>, const std::shared_ptr<RType>&>(
128
14
                   ql_name, param_types, opcode, bfdecl, result);
129
0
    VLOG(3) << "Compiled function call " << ql_name << ". Status: " << s.ToString();
130
14
    return s;
131
14
  }
_ZN2yb4bfql12BFCompileApiINS_2ql6PTExprES3_E16FindQLOpcodeImplINSt3__16vectorENS6_9allocatorINS6_10shared_ptrIS3_EEEEEENS_6StatusERKNS6_12basic_stringIcNS6_11char_traitsIcEENS8_IcEEEERKT_ISA_T0_EPNS0_8BFOpcodeEPPKNS0_6BFDeclERKSA_
Line
Count
Source
126
1.06k
                                  const std::shared_ptr<RType>& result) {
127
1.06k
    Status s = FindOpcode<CType<std::shared_ptr<PType>, AType>, const std::shared_ptr<RType>&>(
128
1.06k
                   ql_name, param_types, opcode, bfdecl, result);
129
0
    VLOG(3) << "Compiled function call " << ql_name << ". Status: " << s.ToString();
130
1.06k
    return s;
131
1.06k
  }
132
133
  // Interface for any collections of raw pointers.
134
  template<template<typename, typename> class CType, typename AType>
135
  static Status FindQLOpcodeImpl(const string& ql_name,
136
                                  const CType<PType*, AType>& param_types,
137
                                  BFOpcode *opcode,
138
                                  const BFDecl **bfdecl,
139
                                  const std::shared_ptr<RType>& result) {
140
    Status s = FindOpcode<CType<PType*, AType>, const std::shared_ptr<RType>&>(
141
                   ql_name, param_types, opcode, bfdecl, result);
142
    VLOG(3) << "Compiled function call " << ql_name << ". Status: " << s.ToString();
143
    return s;
144
  }
145
146
  //------------------------------------------------------------------------------------------------
147
  // Seeks builtin opcode using the given the std::vector of shared pointers.
148
  static Status FindQLOpcode(const string& ql_name,
149
                              const std::vector<std::shared_ptr<PType>>& param_types,
150
                              BFOpcode *opcode,
151
                              const BFDecl **bfdecl,
152
1.07k
                              const std::shared_ptr<RType>& result) {
153
1.07k
    return FindQLOpcodeImpl<std::vector>(ql_name, param_types, opcode, bfdecl, result);
154
1.07k
  }
_ZN2yb4bfql12BFCompileApiINS0_11BFTestValueES2_E12FindQLOpcodeERKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEERKNS4_6vectorINS4_10shared_ptrIS2_EENS8_ISF_EEEEPNS0_8BFOpcodeEPPKNS0_6BFDeclERKSF_
Line
Count
Source
152
14
                              const std::shared_ptr<RType>& result) {
153
14
    return FindQLOpcodeImpl<std::vector>(ql_name, param_types, opcode, bfdecl, result);
154
14
  }
_ZN2yb4bfql12BFCompileApiINS_2ql6PTExprES3_E12FindQLOpcodeERKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEERKNS5_6vectorINS5_10shared_ptrIS3_EENS9_ISG_EEEEPNS0_8BFOpcodeEPPKNS0_6BFDeclERKSG_
Line
Count
Source
152
1.06k
                              const std::shared_ptr<RType>& result) {
153
1.06k
    return FindQLOpcodeImpl<std::vector>(ql_name, param_types, opcode, bfdecl, result);
154
1.06k
  }
155
156
  // Seeks builtin opcode using the given the std::vector of raw pointers.
157
  static Status FindQLOpcode(const string& ql_name,
158
                              const std::vector<PType*>& param_types,
159
                              BFOpcode *opcode,
160
                              const BFDecl **bfdecl,
161
                              const std::shared_ptr<RType>& result) {
162
    return FindQLOpcodeImpl<std::vector>(ql_name, param_types, opcode, bfdecl, result);
163
  }
164
165
  // Seeks builtin opcode using the given the std::vector of Datatypes.
166
  static Status FindQLOpcode(const string& ql_name,
167
                              const std::vector<DataType>& actual_types,
168
                              BFOpcode *opcode,
169
                              const BFDecl **bfdecl,
170
106
                              DataType *return_type) {
171
106
    Status s = FindOpcodeByType(ql_name, actual_types, opcode, bfdecl, return_type);
172
0
    VLOG(3) << "Compiled function call " << ql_name << ". Status: " << s.ToString();
173
106
    return s;
174
106
  }
175
176
  // Seeks CAST opcode from one type to another.
177
648
  static Status FindCastOpcode(DataType source, DataType target, BFOpcode *opcode) {
178
648
    if (source == target ||
179
398
        source == DataType::NULL_VALUE_TYPE ||
180
542
        target == DataType::NULL_VALUE_TYPE) {
181
542
      *opcode = yb::bfql::BFOPCODE_NOOP;
182
542
      return Status::OK();
183
542
    }
184
185
    // Find conversion opcode.
186
106
    const BFDecl *found_decl = nullptr;
187
106
    std::vector<DataType> actual_types = { source, target };
188
106
    DataType return_type = DataType::UNKNOWN_DATA;
189
106
    return FindQLOpcode(bfql::kCastFuncName, actual_types, opcode, &found_decl, &return_type);
190
106
  }
191
};
192
193
//--------------------------------------------------------------------------------------------------
194
// class BFExecApi<PType, RType> has one main entry function - ExecQLOpcode().
195
// ExecQLOpcode() executes builtin calls with the given opcode and arguments and writes result
196
// to the output parameter result. It reports error by returning Status.
197
//
198
// NOTES:
199
// The API are using templates which have the following requirements.
200
//
201
// - The datatype of parameters must have the following member functions.
202
//     bool IsNull() const;
203
//     InternalType type() const;
204
//     int8_t int8_value() const;
205
//     int16_t int16_value() const;
206
//     int32_t int32_value() const;
207
//     int64_t int64_value() const;
208
//     float float_value() const;
209
//     double double_value() const;
210
//     bool bool_value() const;
211
//     const std::string& string_value() const;
212
//     Timestamp timestamp_value() const;
213
//     const std::string& binary_value() const;
214
//     InetAddress inetaddress_value() const;
215
//
216
// - The datatype of return-results must have the following member functions.
217
//     void SetNull();
218
//     InternalType type() const;
219
//     void set_int8_value(int8_t val);
220
//     void set_int16_value(int16_t val);
221
//     void set_int32_value(int32_t val);
222
//     void set_int64_value(int64_t val);
223
//     void set_float_value(float val);
224
//     void set_double_value(double val);
225
//     void set_bool_value(bool val);
226
//     void set_string_value(const std::string& val);
227
//     void set_string_value(const char* val);
228
//     void set_string_value(const char* val, size_t size);
229
//     void set_timestamp_value(const Timestamp& val);
230
//     void set_timestamp_value(int64_t val);
231
//     void set_binary_value(const std::string& val);
232
//     void set_binary_value(const void* val, size_t size);
233
//     void set_inetaddress_value(const InetAddress& val);
234
//
235
// - Builtin-calls don't do implicit data conversion. They expect parameters to have the expected
236
//   type, and they always return data of the expected type. Arguments must be converted to correct
237
//   types before passing by using "cast" operator.
238
template<typename PType,
239
         typename RType,
240
         template<typename, typename> class CType = std::vector,
241
         template<typename> class AType = std::allocator>
242
class BFExecApi {
243
 public:
244
  // Declare table of function pointers that take shared_ptr as arguments and returned-result.
245
  static const vector<std::function<Status(const std::vector<std::shared_ptr<PType>>&,
246
                                           const std::shared_ptr<RType>&)>>
247
      kBFExecFuncs;
248
249
  // Declare table of function pointers that take raw pointers as arguments and returned-result.
250
  static const vector<std::function<Status(const std::vector<PType*>&, RType*)>>
251
      kBFExecFuncsRaw;
252
253
  // Declare table of function pointers that take ref as arguments and raw pointers as result
254
  static const vector<std::function<Status(std::vector<PType>*, RType*)>>
255
      kBFExecFuncsRefAndRaw;
256
257
  //------------------------------------------------------------------------------------------------
258
  // Runs the associated entry in the table of function pointers on the given shared_ptrs.
259
  //   kBFExecFuncs[opcode](args)
260
  static Status ExecQLOpcode(BFOpcode opcode,
261
                              const std::vector<std::shared_ptr<PType>>& params,
262
46
                              const std::shared_ptr<RType>& result) {
263
    // TODO(neil) There has to be some sanity error check here.
264
46
    RETURN_NOT_OK(CheckError(opcode, params, result));
265
46
    Status s = kBFExecFuncs[static_cast<int>(opcode)](params, result);
266
0
    VLOG(3) << "Executed builtin call(" << int(opcode) << "). Status: " << s.ToString();
267
46
    return s;
268
46
  }
_ZN2yb4bfql9BFExecApiINS0_11BFTestValueES2_NSt3__16vectorENS3_9allocatorEE12ExecQLOpcodeENS0_8BFOpcodeERKNS4_INS3_10shared_ptrIS2_EENS5_IS9_EEEERKS9_
Line
Count
Source
262
46
                              const std::shared_ptr<RType>& result) {
263
    // TODO(neil) There has to be some sanity error check here.
264
46
    RETURN_NOT_OK(CheckError(opcode, params, result));
265
46
    Status s = kBFExecFuncs[static_cast<int>(opcode)](params, result);
266
0
    VLOG(3) << "Executed builtin call(" << int(opcode) << "). Status: " << s.ToString();
267
46
    return s;
268
46
  }
Unexecuted instantiation: _ZN2yb4bfql9BFExecApiINS_7QLValueES2_NSt3__16vectorENS3_9allocatorEE12ExecQLOpcodeENS0_8BFOpcodeERKNS4_INS3_10shared_ptrIS2_EENS5_IS9_EEEERKS9_
269
270
  // TODO(neil) Because opcodes are created and executed by different processes, some sanity error
271
  // checking must be done at run time in logging mode.
272
  static Status CheckError(BFOpcode opcode,
273
                           const std::vector<std::shared_ptr<PType>>& params,
274
46
                           const std::shared_ptr<RType>& result) {
275
    // TODO(neil) Currently, the execution phase is not yet implemented, so it'd be immature to
276
    // code for error-check here. Once it is implemented, we'll know what to check.
277
0
    if (VLOG_IS_ON(3)) {
278
0
      LOG(INFO) << "Executing opcode " << int(opcode);
279
0
    }
280
46
    return Status::OK();
281
46
  }
_ZN2yb4bfql9BFExecApiINS0_11BFTestValueES2_NSt3__16vectorENS3_9allocatorEE10CheckErrorENS0_8BFOpcodeERKNS4_INS3_10shared_ptrIS2_EENS5_IS9_EEEERKS9_
Line
Count
Source
274
46
                           const std::shared_ptr<RType>& result) {
275
    // TODO(neil) Currently, the execution phase is not yet implemented, so it'd be immature to
276
    // code for error-check here. Once it is implemented, we'll know what to check.
277
0
    if (VLOG_IS_ON(3)) {
278
0
      LOG(INFO) << "Executing opcode " << int(opcode);
279
0
    }
280
46
    return Status::OK();
281
46
  }
Unexecuted instantiation: _ZN2yb4bfql9BFExecApiINS_7QLValueES2_NSt3__16vectorENS3_9allocatorEE10CheckErrorENS0_8BFOpcodeERKNS4_INS3_10shared_ptrIS2_EENS5_IS9_EEEERKS9_
282
283
  //------------------------------------------------------------------------------------------------
284
  // Runs the associated entry in the table of function pointers on the given raw pointers.
285
  //   kBFExecFuncsRaw[opcode](args)
286
  static Status ExecQLOpcode(BFOpcode opcode,
287
                              const std::vector<PType*>& params,
288
2
                              RType *result) {
289
    // TODO(neil) There has to be some sanity error check here.
290
2
    RETURN_NOT_OK(CheckError(opcode, params, result));
291
2
    Status s = kBFExecFuncsRaw[static_cast<int>(opcode)](params, result);
292
0
    VLOG(3) << "Executed builtin call(" << int(opcode) << "). Status: " << s.ToString();
293
2
    return s;
294
2
  }
_ZN2yb4bfql9BFExecApiINS0_11BFTestValueES2_NSt3__16vectorENS3_9allocatorEE12ExecQLOpcodeENS0_8BFOpcodeERKNS4_IPS2_NS5_IS8_EEEES8_
Line
Count
Source
288
2
                              RType *result) {
289
    // TODO(neil) There has to be some sanity error check here.
290
2
    RETURN_NOT_OK(CheckError(opcode, params, result));
291
2
    Status s = kBFExecFuncsRaw[static_cast<int>(opcode)](params, result);
292
0
    VLOG(3) << "Executed builtin call(" << int(opcode) << "). Status: " << s.ToString();
293
2
    return s;
294
2
  }
Unexecuted instantiation: _ZN2yb4bfql9BFExecApiINS_7QLValueES2_NSt3__16vectorENS3_9allocatorEE12ExecQLOpcodeENS0_8BFOpcodeERKNS4_IPS2_NS5_IS8_EEEES8_
295
296
  static Status CheckError(BFOpcode opcode,
297
                           const std::vector<PType*>& params,
298
2
                           RType *result) {
299
    // TODO(neil) Currently, the execution phase is not yet implemented, so it'd be immature to
300
    // code for error-check here. Once it is implemented, we'll know what to check.
301
0
    if (VLOG_IS_ON(3)) {
302
0
      LOG(INFO) << "Executing opcode " << int(opcode);
303
0
    }
304
2
    return Status::OK();
305
2
  }
_ZN2yb4bfql9BFExecApiINS0_11BFTestValueES2_NSt3__16vectorENS3_9allocatorEE10CheckErrorENS0_8BFOpcodeERKNS4_IPS2_NS5_IS8_EEEES8_
Line
Count
Source
298
2
                           RType *result) {
299
    // TODO(neil) Currently, the execution phase is not yet implemented, so it'd be immature to
300
    // code for error-check here. Once it is implemented, we'll know what to check.
301
0
    if (VLOG_IS_ON(3)) {
302
0
      LOG(INFO) << "Executing opcode " << int(opcode);
303
0
    }
304
2
    return Status::OK();
305
2
  }
Unexecuted instantiation: _ZN2yb4bfql9BFExecApiINS_7QLValueES2_NSt3__16vectorENS3_9allocatorEE10CheckErrorENS0_8BFOpcodeERKNS4_IPS2_NS5_IS8_EEEES8_
306
307
  //------------------------------------------------------------------------------------------------
308
  // Runs the associated entry in the table of function pointers on the given raw pointers.
309
  //   kBFExecFuncsRefAndRaw[opcode](args)
310
  static Status ExecQLOpcode(BFOpcode opcode,
311
                              std::vector<PType> *params,
312
724
                              RType *result) {
313
    // TODO(neil) There has to be some sanity error check here.
314
724
    RETURN_NOT_OK(CheckError(opcode, params, result));
315
724
    Status s = kBFExecFuncsRefAndRaw[static_cast<int>(opcode)](params, result);
316
0
    VLOG(3) << "Executed builtin call(" << int(opcode) << "). Status: " << s.ToString();
317
724
    return s;
318
724
  }
319
320
  static Status CheckError(BFOpcode opcode,
321
                           std::vector<PType> *params,
322
724
                           RType *result) {
323
    // TODO(neil) Currently, the execution phase is not yet implemented, so it'd be immature to
324
    // code for error-check here. Once it is implemented, we'll know what to check.
325
0
    if (VLOG_IS_ON(3)) {
326
0
      LOG(INFO) << "Executing opcode " << int(opcode);
327
0
    }
328
724
    return Status::OK();
329
724
  }
330
};
331
332
//--------------------------------------------------------------------------------------------------
333
// This class is conveniently and ONLY for testing purpose. It executes builtin calls by names
334
// instead of opcode.
335
template<typename PType,
336
         typename RType,
337
         template<typename, typename> class CType = std::vector,
338
         template<typename> class AType = std::allocator>
339
class BFExecImmediateApi : public BFExecApi<PType, RType, CType, AType> {
340
 public:
341
  // Interface for shared_ptr.
342
  static Status ExecQLFunc(const string& ql_name,
343
                            const std::vector<std::shared_ptr<PType>>& params,
344
74
                            const std::shared_ptr<RType>& result) {
345
74
    BFOpcode opcode;
346
74
    const BFDecl *bfdecl;
347
74
    RETURN_NOT_OK((FindOpcode<std::vector<std::shared_ptr<PType>>, const std::shared_ptr<RType>&>(
348
74
        ql_name, params, &opcode, &bfdecl, result)));
349
41
    return BFExecApi<PType, RType>::ExecQLOpcode(opcode, params, result);
350
74
  }
351
352
  // Interface for raw pointer.
353
  static Status ExecQLFunc(const string& ql_name,
354
                            const std::vector<PType*>& params,
355
4
                            RType *result) {
356
4
    BFOpcode opcode;
357
4
    const BFDecl *bfdecl;
358
4
    RETURN_NOT_OK(
359
4
        (FindOpcode<std::vector<PType*>, RType*>(ql_name, params, &opcode, &bfdecl, result)));
360
2
    return BFExecApi<PType, RType>::ExecQLOpcode(opcode, params, result);
361
4
  }
362
};
363
364
} // namespace bfql
365
} // namespace yb
366
367
//--------------------------------------------------------------------------------------------------
368
// Generated tables "kBFExecFuncs" and "kBFExecFuncsRaw".
369
// Because the tables must be initialized after the specification for "class BFExecApi", we have to
370
// include header file "gen_bfunc_table.h" at the end of this file.
371
#include "yb/bfql/gen_bfunc_table.h"
372
373
#endif  // YB_BFQL_BFQL_H_