1 /* 2 Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License, version 2.0, for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 23 24 #ifndef NdbQueryOperation_H 25 #define NdbQueryOperation_H 26 27 #include <ndb_types.h> 28 29 // this file is currently not located in include/ndbapi 30 // which means that we need to use <> to include instead of "" 31 // for files located in include/ndbapi 32 33 // this file is currently not located in include/ndbapi 34 // skip includes...and require them to be included first 35 // BUH! 36 37 /* There is no way to forward declare nested class NdbDictionary::Column, 38 * so this header file must be included.*/ 39 // #include <NdbDictionary.hpp> 40 41 // Needed to get NdbQueryOptions::ScanOrdering. 42 // #include "NdbQueryBuilder.hpp" 43 // #include <NdbIndexScanOperation.hpp> 44 45 46 class Ndb; 47 struct NdbError; 48 class NdbParamOperand; 49 class NdbQueryOperation; 50 class NdbQueryOperationDef; 51 class NdbRecAttr; 52 class NdbTransaction; 53 class NdbRecord; 54 class NdbInterpretedCode; 55 56 /** Opaque implementation classes*/ 57 class NdbQueryImpl; 58 class NdbQueryOperationImpl; 59 60 61 /********************** OVERVIEW *********************** 62 * 63 * a NdbQuery is created when a NdbQueryDefinition is added to a 64 * NdbTransaction for execution with NdbTransaction::creatQuery(). 65 * 66 * A NdbQuery is associated with a collection of NdbQueryOperation which 67 * are instantiated (1::1) to reflect the NdbQueryOperationDef objects 68 * which the NdbQueryDef consists of. The same NdbQueryDef may be used to 69 * instantiate multiple NdbQuery obejects. 70 * 71 * When we have an instantiated NdbQuery, we should either bind result buffers 72 * for retrieving entire rows from each operation, 73 * (aka NdbRecord interface,::setResultRowRef(), ::setResultRowBuf()) 74 * or set up retrieval operations for each attribute values, (::getValue()). 75 * 76 * Optionally we may also: 77 * - Specify a scan ordering for the result set (parent only) 78 * - Add multiple bounds to a range scan, (::setBound()) (parent only) 79 * - Append a filter condition for each operation (aka mysqlds pushed condition) 80 * 81 * The NdbQuery is then executed together with other pending operations 82 * in the next NdbTransaction::execute(). 83 * The resultset available from a NdbQuery is natively a 'left outer join' 84 * between the parent / child operations. If an application is not interested 85 * in the 'outer part' of the resultset, it is its own responsibility to 86 * filter these rows. Same is valid for any filter condition which has 87 * not been appended to the NdbQuery. 88 * 89 * 90 * We provide two different interfaces for iterating the result set: 91 * 92 * The 'local cursor' (NdbQueryOperation::firstResult(), ::nextResult()) 93 * Will navigate the resultset, and fetch results, from this specific operation. 94 * It will only be possible to navigate within those rows which depends 95 * on the current row(s) from any ancestor of the operation. 96 * The local cursor will only retrieve the results, or a NULL row, 97 * resulting from its own operation. -> All child operations of a 98 * renavigated local cursor should be navigated to ::firstResult() 99 * to ensure that they contain results related to the renavigated parent. 100 * 101 * The 'global cursor' (NdbQuery::nextResult()) 102 * Will present the result set as a scan on the root operation 103 * with rows from its child operations appearing in an unpredictable 104 * order. A new set of results, or NULL rows, from *all* operations 105 * in the query tree are retrieved for each ::nextResult(). 106 * NULL rows resulting from the outer joins may appear anywhere 107 * inside the resultset. 108 * 109 * As the global cursor is implemented on top of the local cursors, it is 110 * possible to mix the usage of global and local cursors. 111 * 112 ************************************************************************/ 113 class NdbQuery 114 { 115 private: 116 // Only constructable through ::buildQuery() 117 friend class NdbQueryImpl; 118 explicit NdbQuery(NdbQueryImpl& impl); 119 ~NdbQuery(); 120 121 public: 122 /** Possible return values from nextResult().*/ 123 enum NextResultOutcome{ 124 NextResult_error = -1, 125 NextResult_gotRow = 0, 126 NextResult_scanComplete = 1, 127 NextResult_bufferEmpty = 2 128 }; 129 130 Uint32 getNoOfOperations() const; 131 132 // Get a specific NdbQueryOperation by ident specified 133 // when the NdbQueryOperationDef was created. 134 NdbQueryOperation* getQueryOperation(const char* ident) const; 135 NdbQueryOperation* getQueryOperation(Uint32 index) const; 136 //NdbQueryOperation* getQueryOperation(const NdbQueryOperationDef* def) const; 137 138 Uint32 getNoOfParameters() const; 139 const NdbParamOperand* getParameter(const char* name) const; 140 const NdbParamOperand* getParameter(Uint32 num) const; 141 142 int setBound(const NdbRecord *keyRecord, 143 const struct NdbIndexScanOperation::IndexBound *bound); 144 145 /** 146 * Get the next tuple(s) from the global cursor on the query. 147 * 148 * Result row / columns will be updated in the respective result handlers 149 * as previously specified on each NdbQueryOperation either by assigning a 150 * NdbRecord/rowBuffer or assigning NdbRecAttr to each column to be retrieved. 151 * 152 * @param fetchAllowed If set to false, then fetching is disabled 153 * @param forceSend If true send will occur immediately (see @ref secAdapt) 154 * 155 * When fetchAllowed is set to false, 156 * the NDB API will not request new batches from the NDB Kernel when 157 * all received rows have been exhausted, but will instead return 2 158 * from nextResult(), indicating that new batches must be 159 * requested. You must then call nextResult with fetchAllowed = true 160 * in order to contact the NDB Kernel for more records, after taking over 161 * locks as appropriate. 162 * 163 * @note: All result returned from a NdbQuery are handled as scan results 164 * in a cursor like interface.(Even single tuple 'lookup' operations!) 165 * - After ::execute() the current position of the result set is 'before' 166 * the first row. There is no valid data yet in the 'RecAttr' 167 * or NdbRecord associated with the NdbQueryOperation! 168 * - ::nextResult() is required to retrieve the first row. This may 169 * also cause any error / status info assicioated with the result set 170 * iself to be returned (Like 'NoData', posible type conversion errors, 171 * or constraint violations associated with each specific row in the 172 * result set.) 173 * 174 * @return 175 * - NextResult_error (-1): if unsuccessful,<br> 176 * - NextResult_gotRow (0): if another tuple was received, and<br> 177 * - NextResult_scanComplete (1): if there are no more tuples to scan. 178 * - NextResult_bufferEmpty (2): if there are no more cached records 179 * in NdbApi 180 */ 181 NextResultOutcome nextResult(bool fetchAllowed = true, 182 bool forceSend = false); 183 184 /** 185 * Get NdbTransaction object for this query operation 186 */ 187 NdbTransaction* getNdbTransaction() const; 188 189 /** 190 * Close query. 191 * 192 * Will release most of the internally allocated objects owned 193 * by this NdbQuery and detach itself from the NdbQueryDef 194 * used to instantiate it. 195 * 196 * The application may destruct the NdbQueryDef after 197 * ::close() has been called on *all* NdbQuery objects 198 * instantiated from it. 199 */ 200 void close(bool forceSend = false); 201 202 /** 203 * @name Error Handling 204 * @{ 205 */ 206 207 /** 208 * Get error object with information about the latest error. 209 * 210 * @return An error object with information about the latest error. 211 */ 212 const NdbError& getNdbError() const; 213 214 /** Get object implementing NdbQuery interface.*/ getImpl() const215 NdbQueryImpl& getImpl() const 216 { return m_impl; } 217 218 /** 219 * Check if this is a pruned range scan. A range scan is pruned if the ranges 220 * are such that only a subset of the fragments need to be scanned for 221 * matching tuples. 222 * 223 * @param pruned This will be set to true if the operation is a pruned range 224 * scan. 225 * @return 0 if ok, -1 in case of error (call getNdbError() for details.) 226 */ 227 int isPrunable(bool& pruned) const; 228 229 private: 230 /** Opaque implementation NdbQuery interface.*/ 231 NdbQueryImpl& m_impl; 232 233 }; // class NdbQuery 234 235 236 237 238 class NdbQueryOperation 239 { 240 private: 241 // Only constructable through executing a NdbQueryDef 242 friend class NdbQueryOperationImpl; 243 explicit NdbQueryOperation(NdbQueryOperationImpl& impl); 244 ~NdbQueryOperation(); 245 246 public: 247 // Collection of get'ers to navigate in root, parent/child hierarchy 248 249 Uint32 getNoOfParentOperations() const; 250 NdbQueryOperation* getParentOperation(Uint32 parentNo) const; 251 252 Uint32 getNoOfChildOperations() const; 253 NdbQueryOperation* getChildOperation(Uint32 childNo) const; 254 255 const NdbQueryOperationDef& getQueryOperationDef() const; 256 257 // Get the entire query object which this operation is part of 258 NdbQuery& getQuery() const; 259 260 261 262 /** 263 * Defines a retrieval operation of an attribute value. 264 * The NDB API allocate memory for the NdbRecAttr object that 265 * will hold the returned attribute value. 266 * 267 * @note Note that it is the applications responsibility 268 * to allocate enough memory for resultBuffer (if non-NULL). 269 * The buffer resultBuffer supplied by the application must be 270 * aligned appropriately. The buffer is used directly 271 * (avoiding a copy penalty) only if it is aligned on a 272 * 4-byte boundary and the attribute size in bytes 273 * (i.e. NdbRecAttr::attrSize times NdbRecAttr::arraySize is 274 * a multiple of 4). 275 * 276 * @note There are three versions of NdbQueryOperation::getValue with 277 * slightly different parameters. 278 * 279 * @note This method does not fetch the attribute value from 280 * the database! The NdbRecAttr object returned by this method 281 * is <em>not</em> readable/printable before the 282 * transaction has been executed with NdbTransaction::execute. 283 * 284 * @param anAttrName Attribute name 285 * @param resultBuffer If this is non-NULL, then the attribute value 286 * will be returned in this parameter.<br> 287 * If NULL, then the attribute value will only 288 * be stored in the returned NdbRecAttr object. 289 * @return An NdbRecAttr object to hold the value of 290 * the attribute, or a NULL pointer 291 * (indicating error). 292 */ 293 NdbRecAttr* getValue(const char* anAttrName, char* resultBuffer = 0); 294 NdbRecAttr* getValue(Uint32 anAttrId, char* resultBuffer = 0); 295 NdbRecAttr* getValue(const NdbDictionary::Column* column, 296 char* resultBuffer = 0); 297 298 /** 299 * Retrieval of entire or partial rows may also be specified. For partial 300 * retrieval a bitmask should supplied. 301 * 302 * The behaviour of mixing NdbRecord retrieval style with NdbRecAttr is 303 * is undefined - It should probably not be allowed. 304 * 305 * @param rec Is a pointer to a NdbRecord specifying the byte layout of the 306 * result row. 307 * 308 * @resBuffer Defines a buffer sufficient large to hold the result row. 309 * 310 * @bufRef Refers a pointer which will be updated to refer the current result row 311 * for this operand. 312 * 313 * @param result_mask defines as subset of attributes to read. 314 * The column is only affected if 'mask[attrId >> 3] & (1<<(attrId & 7))' is set 315 * @return 0 on success, -1 otherwise (call getNdbError() for details). 316 */ 317 int setResultRowBuf (const NdbRecord *rec, 318 char* resBuffer, 319 const unsigned char* result_mask = 0); 320 321 int setResultRowRef (const NdbRecord* rec, 322 const char* & bufRef, 323 const unsigned char* result_mask = 0); 324 325 // TODO: define how BLOB/CLOB should be retrieved. 326 // ... Replicate ::getBlobHandle() from NdbOperation class? 327 328 /** Get object implementing NdbQueryOperation interface.*/ getImpl() const329 NdbQueryOperationImpl& getImpl() const 330 { return m_impl; } 331 332 /** Define result ordering for ordered index scan. It is an error to call 333 * this method on an operation that is not a scan, or to call it if an 334 * ordering was already set on the operation defintion by calling 335 * NdbQueryOperationDef::setOrdering(). 336 * @param ordering The desired ordering of results. 337 * @return 0 if ok, -1 in case of error (call getNdbError() for details.) 338 */ 339 int setOrdering(NdbQueryOptions::ScanOrdering ordering); 340 341 /** Get the result ordering for this operation.*/ 342 NdbQueryOptions::ScanOrdering getOrdering() const; 343 344 /** 345 * Set the number of fragments to be scanned in parallel. This only applies 346 * to table scans and non-sorted scans of ordered indexes. This method is 347 * only implemented for then root scan operation. 348 * @return 0 if ok, -1 in case of error (call getNdbError() for details.) 349 */ 350 int setParallelism(Uint32 parallelism); 351 352 /** 353 * Set the number of fragments to be scanned in parallel to the maximum 354 * possible value. This is the default for the root scan operation. 355 * @return 0 if ok, -1 in case of error (call getNdbError() for details.) 356 */ 357 int setMaxParallelism(); 358 359 /** 360 * Let the system dynamically choose the number of fragments to scan in 361 * parallel. The system will try to choose a value that gives optimal 362 * performance. This is the default for all scans but the root scan. This 363 * method only implemented for non-root scan operations. 364 * @return 0 if ok, -1 in case of error (call getNdbError() for details.) 365 */ 366 int setAdaptiveParallelism(); 367 368 /** Set the batch size (max rows per batch) for this operation. This 369 * only applies to scan operations, as lookup operations always will 370 * have the same batch size as its parent operation, or 1 if it is the 371 * root operation. 372 * @param batchSize Batch size (in number of rows). A value of 0 means 373 * use the default batch size. 374 * @return 0 if ok, -1 in case of error (call getNdbError() for details.) 375 */ 376 int setBatchSize(Uint32 batchSize); 377 378 /** 379 * Set the NdbInterpretedCode needed for defining a conditional filter 380 * (aka: predicate) for this operation. Might be used both on scan 381 * and lookup operations. 382 * 383 * Typically, one would create NdbScanFilter and NdbInterpretedCode objects 384 * on the stack, e.g.: 385 * NdbInterpretedCode code(table); 386 * NdbScanFilter filter(code); 387 * filter.begin(); 388 * filter.ge(0, 5U); // Check if column 1 is greater of equal to 5. 389 * filter.end(); 390 * queryOp->setInterpretedCode(code); 391 * 392 * @param code The interpreted code. This object is copied internally, 393 * meaning that 'code' may be destroyed as soon as this method returns. 394 * @return 0 if ok, -1 in case of error (call getNdbError() for details.) 395 */ 396 int setInterpretedCode(const NdbInterpretedCode& code) const; 397 398 /** 399 * Local cursor: 400 * 401 * Navigate to first result row in this batch of results which 402 * depends on the current row(s) from all its ancestors. 403 * @return 404 * - NextResult_error (-1): if unsuccessful,<br> 405 * - NextResult_gotRow (0): if another tuple was received, and<br> 406 * - NextResult_scanComplete (1): if there are no more tuples to scan. 407 * - NextResult_bufferEmpty (2): if there are no more cached records 408 * in NdbApi 409 */ 410 NdbQuery::NextResultOutcome firstResult(); 411 412 /** 413 * Local cursor: 414 * 415 * Get the next tuple(s) from this operation (and all its descendants?) 416 * which depends on the current row(s) from all its ancestors. 417 * 418 * Result row / columns will be updated in the respective result handlers 419 * as previously specified on each NdbQueryOperation either by assigning a 420 * NdbRecord/rowBuffer or assigning NdbRecAttr to each column to be retrieved. 421 * 422 * If the set of cached records in the NdbApi has been consumed, more will be 423 * requested from the datanodes only iff: 424 * - This NdbOperation is the root of the entire pushed NdbQuery. 425 * - 'fetchAllowed==true' 426 * 427 * The arguments fetchAllowed and forceSend are ignored if this operation is 428 * not the root of the pushed query. 429 * 430 * @return 431 * - NextResult_error (-1): if unsuccessful,<br> 432 * - NextResult_gotRow (0): if another tuple was received, and<br> 433 * - NextResult_scanComplete (1): if there are no more tuples to scan. 434 * - NextResult_bufferEmpty (2): if there are no more cached records 435 * in NdbApi 436 */ 437 NdbQuery::NextResultOutcome nextResult( 438 bool fetchAllowed = true, 439 bool forceSend = false); 440 441 // Result handling for this NdbQueryOperation 442 bool isRowNULL() const; // Row associated with Operation is NULL value? 443 444 bool isRowChanged() const; // Prev ::nextResult() on NdbQuery retrived a new 445 // value for this NdbQueryOperation 446 447 448 private: 449 // Opaque implementation class instance. 450 NdbQueryOperationImpl& m_impl; 451 452 }; // class NdbQueryOperation 453 454 455 class NdbQueryParamValue 456 { 457 public: 458 459 // Raw data formated according to bound Column format. 460 // NOTE: This is how mysqld prepare parameter values! 461 NdbQueryParamValue(const void* val, bool shrinkVarChar= false); 462 463 // C-type string, terminated by '\0' 464 NdbQueryParamValue(const char* val); 465 466 // NULL-value, also used as optional end marker 467 NdbQueryParamValue(); 468 NdbQueryParamValue(Uint16 val); 469 NdbQueryParamValue(Uint32 val); 470 NdbQueryParamValue(Uint64 val); 471 NdbQueryParamValue(double val); 472 473 // More parameter C'tor to be added when required: 474 //NdbQueryParamValue(Uint8 val); 475 //NdbQueryParamValue(Int8 val); 476 //NdbQueryParamValue(Int16 val); 477 //NdbQueryParamValue(Int32 val); 478 //NdbQueryParamValue(Int64 val); 479 480 /** 481 * Serialize value into a seuqence of words suitable to be sent to the data 482 * nodes. 483 * @param column Specifies the format that the value should be serialized 484 * into. 485 * @param dst Seralized data are appended to this. 486 * @param len Length of serialized data (in number of bytes). 487 * @param isNull Will be set to true iff this is a NULL value. 488 * @return 0 if ok, otherwise an error code. 489 */ 490 int serializeValue(const class NdbColumnImpl& column, 491 class Uint32Buffer& dst, 492 Uint32& len, 493 bool& isNull) const; 494 495 private: 496 int m_type; 497 498 union 499 { 500 Uint8 uint8; 501 Int8 int8; 502 Uint16 uint16; 503 Int16 int16; 504 Uint32 uint32; 505 Int32 int32; 506 Uint64 uint64; 507 Int64 int64; 508 double dbl; 509 const char* string; 510 const void* raw; 511 } m_value; 512 }; 513 514 #endif 515