YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/yql/pggate/pg_dml.h
Line
Count
Source
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
#ifndef YB_YQL_PGGATE_PG_DML_H_
16
#define YB_YQL_PGGATE_PG_DML_H_
17
18
#include <boost/unordered_map.hpp>
19
20
#include "yb/yql/pggate/pg_doc_op.h"
21
#include "yb/yql/pggate/pg_session.h"
22
#include "yb/yql/pggate/pg_statement.h"
23
#include "yb/yql/pggate/pg_table.h"
24
25
namespace yb {
26
namespace pggate {
27
28
//--------------------------------------------------------------------------------------------------
29
// DML
30
//--------------------------------------------------------------------------------------------------
31
class PgSelectIndex;
32
33
class PgDml : public PgStatement {
34
 public:
35
  virtual ~PgDml();
36
37
  // Append a target in SELECT or RETURNING.
38
  CHECKED_STATUS AppendTarget(PgExpr *target);
39
40
  // Append a filter condition.
41
  // Supported expression kind is serialized Postgres expression
42
  CHECKED_STATUS AppendQual(PgExpr *qual);
43
44
  // Append a column reference.
45
  // If any serialized Postgres expressions appended to other lists require explicit addition
46
  // of their column references. Those column references should have Postgres type information.
47
  // Other PgExpr kinds are automatically scanned and their column references are appended.
48
  CHECKED_STATUS AppendColumnRef(PgExpr *colref);
49
50
  // Prepare column for both ends.
51
  // - Prepare protobuf to communicate with DocDB.
52
  // - Prepare PgExpr to send data back to Postgres layer.
53
  Result<const PgColumn&> PrepareColumnForRead(int attr_num, PgsqlExpressionPB *target_pb);
54
  CHECKED_STATUS PrepareColumnForWrite(PgColumn *pg_col, PgsqlExpressionPB *assign_pb);
55
56
  // Bind a column with an expression.
57
  // - For a secondary-index-scan, this bind specify the value of the secondary key which is used to
58
  //   query a row.
59
  // - For a primary-index-scan, this bind specify the value of the keys of the table.
60
  CHECKED_STATUS BindColumn(int attnum, PgExpr *attr_value);
61
62
  // Bind the whole table.
63
  CHECKED_STATUS BindTable();
64
65
  // Assign an expression to a column.
66
  CHECKED_STATUS AssignColumn(int attnum, PgExpr *attr_value);
67
68
  // Process the secondary index request if it is nested within this statement.
69
  Result<bool> ProcessSecondaryIndexRequest(const PgExecParameters *exec_params);
70
71
  // Fetch a row and return it to Postgres layer.
72
  CHECKED_STATUS Fetch(int32_t natts,
73
                       uint64_t *values,
74
                       bool *isnulls,
75
                       PgSysColumns *syscols,
76
                       bool *has_data);
77
78
  // Returns TRUE if docdb replies with more data.
79
  Result<bool> FetchDataFromServer();
80
81
  // Returns TRUE if desired row is found.
82
  Result<bool> GetNextRow(PgTuple *pg_tuple);
83
84
  virtual void SetCatalogCacheVersion(uint64_t catalog_cache_version) = 0;
85
86
  // Get column info on whether the column 'attr_num' is a hash key, a range
87
  // key, or neither.
88
  Result<YBCPgColumnInfo> GetColumnInfo(int attr_num) const;
89
90
  bool has_aggregate_targets();
91
92
5.39M
  bool has_doc_op() const {
93
5.39M
    return doc_op_ != nullptr;
94
5.39M
  }
95
96
 protected:
97
  // Method members.
98
  // Constructor.
99
  PgDml(PgSession::ScopedRefPtr pg_session, const PgObjectId& table_id);
100
  PgDml(PgSession::ScopedRefPtr pg_session,
101
        const PgObjectId& table_id,
102
        const PgObjectId& index_id,
103
        const PgPrepareParameters *prepare_params);
104
105
  // Allocate protobuf for a SELECTed expression.
106
  virtual PgsqlExpressionPB *AllocTargetPB() = 0;
107
108
  // Allocate protobuf for a WHERE clause expression.
109
  // Subclasses use different protobuf message types for their requests, so they should
110
  // implement this method that knows how to add a PgsqlExpressionPB entry into their where_clauses
111
  // field.
112
  virtual PgsqlExpressionPB *AllocQualPB() = 0;
113
114
  // Allocate protobuf for expression whose value is bounded to a column.
115
  virtual PgsqlExpressionPB *AllocColumnBindPB(PgColumn *col) = 0;
116
117
  // Allocate protobuf for expression whose value is assigned to a column (SET clause).
118
  virtual PgsqlExpressionPB *AllocColumnAssignPB(PgColumn *col) = 0;
119
120
  // Specify target of the query in protobuf request.
121
  CHECKED_STATUS AppendTargetPB(PgExpr *target);
122
123
  // Update bind values.
124
  CHECKED_STATUS UpdateBindPBs();
125
126
  // Update set values.
127
  CHECKED_STATUS UpdateAssignPBs();
128
129
  // Compatibility: set deprecated column_refs for legacy nodes
130
  // We are deprecating PgsqlColumnRefsPB protobuf since it does not allow to transfer Postgres
131
  // type information required to evaluate serialized Postgres expressions.
132
  // It is being replaced by list of PgsqlColRefPB entries, which is set by ColRefsToPB.
133
  // While there is are chance of cluster being upgraded from older version, we have to populate
134
  // both.
135
  void ColumnRefsToPB(PgsqlColumnRefsPB *column_refs);
136
137
  // Transfer columns information from target_.columns() to the request's col_refs list field.
138
  // Subclasses use different protobuf message types to make requests, so they must implement
139
  // the ClearColRefPBs and AllocColRefPB virtual methods to respectively remove all old col_refs
140
  // entries and allocate new entry in their requests.
141
  void ColRefsToPB();
142
143
  // Clear previously allocated PgsqlColRefPB entries from the protobuf request
144
  virtual void ClearColRefPBs() = 0;
145
146
  // Allocate a PgsqlColRefPB entriy in the protobuf request
147
  virtual PgsqlColRefPB *AllocColRefPB() = 0;
148
149
  // -----------------------------------------------------------------------------------------------
150
  // Data members that define the DML statement.
151
152
  // Table identifiers
153
  // - table_id_ identifies the table to read data from.
154
  // - index_id_ identifies the index to be used for scanning.
155
  //
156
  // Example for query on table_id_ using index_id_.
157
  //   SELECT FROM "table_id_"
158
  //     WHERE ybctid IN (SELECT base_ybctid FROM "index_id_" WHERE matched-index-binds)
159
  //
160
  // - Postgres will create PgSelect(table_id_) { nested PgSelectIndex (index_id_) }
161
  // - When bind functions are called, it bind user-values to columns in PgSelectIndex as these
162
  //   binds will be used to find base_ybctid from the IndexTable.
163
  // - When AddTargets() is called, the target is added to PgSlect as data will be reading from
164
  //   table_id_ using the found base_ybctid from index_id_.
165
  PgObjectId table_id_;
166
  PgObjectId index_id_;
167
168
  // Targets of statements (Output parameter).
169
  // - "target_desc_" is the table descriptor where data will be read from.
170
  // - "targets_" are either selected or returned expressions by DML statements.
171
  PgTable target_;
172
  std::vector<PgExpr*> targets_;
173
174
  // Qual is a where clause condition pushed to the DocDB to filter scanned rows
175
  // Qual supports PgExprs holding serialized Postgres expressions, and require the column
176
  // references used in these Quals to be explicitly added with AppendColumnRef()
177
  std::vector<PgExpr*> quals_;
178
179
  // bind_desc_ is the descriptor of the table whose key columns' values will be specified by the
180
  // the DML statement being executed.
181
  // - For primary key binding, "bind_desc_" is the descriptor of the main table as we don't have
182
  //   a separated primary-index table.
183
  // - For secondary key binding, "bind_desc_" is the descriptor of teh secondary index table.
184
  //   The bound values will be used to read base_ybctid which is then used to read actual data
185
  //   from the main table.
186
  PgTable bind_;
187
188
  // Prepare control parameters.
189
  PgPrepareParameters prepare_params_ = { .index_oid = kInvalidOid,
190
                                          .index_only_scan = false,
191
                                          .use_secondary_index = false,
192
                                          .querying_colocated_table = false };
193
194
  // -----------------------------------------------------------------------------------------------
195
  // Data members for nested query: This is used for an optimization in PgGate.
196
  //
197
  // - Each DML operation can be understood as
198
  //     Read / Write TABLE WHERE ybctid IN (SELECT ybctid from INDEX).
199
  // - In most cases, the Postgres layer processes the subquery "SELECT ybctid from INDEX".
200
  // - Under certain conditions, to optimize the performance, the PgGate layer might operate on
201
  //   the INDEX subquery itself.
202
  std::unique_ptr<PgSelectIndex> secondary_index_query_;
203
204
  // -----------------------------------------------------------------------------------------------
205
  // Data members for generated protobuf.
206
  // NOTE:
207
  // - Where clause processing data is not supported yet.
208
  // - Some protobuf structure are also set up in PgColumn class.
209
210
  // Column associated values (expressions) to be used by DML statements.
211
  // - When expression are constructed, we bind them with their associated protobuf.
212
  // - These expressions might not yet have values for place_holders or literals.
213
  // - During execution, the place_holder values are updated, and the statement protobuf need to
214
  //   be updated accordingly.
215
  //
216
  // * Bind values are used to identify the selected rows to be operated on.
217
  // * Set values are used to hold columns' new values in the selected rows.
218
  bool ybctid_bind_ = false;
219
  boost::unordered_map<PgsqlExpressionPB*, PgExpr*> expr_binds_;
220
  std::unordered_map<PgsqlExpressionPB*, PgExpr*> expr_assigns_;
221
222
  // Used for colocated TRUNCATE that doesn't bind any columns.
223
  bool bind_table_ = false;
224
225
  // DML Operator.
226
  PgDocOp::SharedPtr doc_op_;
227
228
  //------------------------------------------------------------------------------------------------
229
  // Data members for navigating the output / result-set from either seleted or returned targets.
230
  std::list<PgDocResult> rowsets_;
231
  int64_t current_row_order_ = 0;
232
233
  // Yugabyte has a few IN/OUT parameters of statement execution, "pg_exec_params_" is used to sent
234
  // OUT value back to postgres.
235
  const PgExecParameters *pg_exec_params_ = NULL;
236
237
  //------------------------------------------------------------------------------------------------
238
  // Hashed and range values/components used to compute the tuple id.
239
  //
240
  // These members are populated by the AddYBTupleIdColumn function and the tuple id is retrieved
241
  // using the GetYBTupleId function.
242
  //
243
  // These members are not used internally by the statement and are simply a utility for computing
244
  // the tuple id (ybctid).
245
};
246
247
}  // namespace pggate
248
}  // namespace yb
249
250
#endif // YB_YQL_PGGATE_PG_DML_H_