Code_query.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <common/StmtArea.hpp>
  14. #include "Code_query.hpp"
  15. #include "Code_query_project.hpp"
  16. #include "Code_query_count.hpp"
  17. // Plan_query
  18. Plan_query::~Plan_query()
  19. {
  20. }
  21. Plan_expr_row*
  22. Plan_query::getRow()
  23. {
  24.     ctx_assert(false);
  25.     return 0;
  26. }
  27. void
  28. Plan_query::describe(Ctx& ctx)
  29. {
  30.     const Plan_expr_row* exprRow = getRow();
  31.     const unsigned count = exprRow->getSize();
  32.     // create IRD
  33.     DescArea& ird = descArea(Desc_usage_IRD);
  34.     ird.setCount(ctx, count);
  35.     for (unsigned i = 1; i <= count; i++) {
  36. DescRec& rec = ird.getRecord(i);
  37. const Plan_expr* expr = exprRow->m_exprList[i];
  38. const SqlType& sqlType = expr->sqlType();
  39. // data type
  40. SQLSMALLINT desc_TYPE = sqlType.type();
  41. rec.setField(SQL_DESC_TYPE, desc_TYPE);
  42. SQLSMALLINT desc_CONCISE_TYPE = desc_TYPE;
  43. rec.setField(SQL_DESC_CONCISE_TYPE, desc_CONCISE_TYPE);
  44. SQLSMALLINT desc_DESC_DATETIME_INTERVAL_CODE = 0;
  45. rec.setField(SQL_DESC_DATETIME_INTERVAL_CODE, desc_DESC_DATETIME_INTERVAL_CODE);
  46. // nullable
  47. SQLSMALLINT desc_NULLABLE = sqlType.nullable() ? SQL_NULLABLE : SQL_NO_NULLS;
  48. rec.setField(SQL_DESC_NULLABLE, desc_NULLABLE);
  49. // unsigned
  50. SQLSMALLINT desc_UNSIGNED;
  51. switch (sqlType.type()) {
  52. case SQL_SMALLINT:
  53. case SQL_INTEGER:
  54. case SQL_BIGINT:
  55.     desc_UNSIGNED = sqlType.unSigned() ? SQL_TRUE : SQL_FALSE;
  56.     break;
  57. default:
  58.     desc_UNSIGNED = SQL_TRUE; // thus spake microsoft
  59.     break;
  60. }
  61. rec.setField(SQL_DESC_UNSIGNED, desc_UNSIGNED);
  62. // sizes
  63. SQLUINTEGER desc_LENGTH = sqlType.length();
  64. rec.setField(SQL_DESC_LENGTH, desc_LENGTH);
  65. SQLINTEGER desc_OCTET_LENGTH = sqlType.size();
  66. rec.setField(SQL_DESC_OCTET_LENGTH, desc_OCTET_LENGTH);
  67. SQLINTEGER desc_DISPLAY_SIZE = sqlType.displaySize();
  68. rec.setField(SQL_DESC_DISPLAY_SIZE, desc_DISPLAY_SIZE);
  69. // name
  70. ctx_assert(i < exprRow->m_aliasList.size());
  71. const char* desc_NAME = exprRow->m_aliasList[i].c_str();
  72. rec.setField(SQL_DESC_NAME, desc_NAME);
  73.     }
  74.     ctx_log3(("describe %u columns done", count));
  75.     stmtArea().setFunction(ctx, "SELECT CURSOR", SQL_DIAG_SELECT_CURSOR);
  76. }
  77. // Exec_query
  78. Exec_query::Code::~Code()
  79. {
  80. }
  81. Exec_query::Data::~Data()
  82. {
  83.     delete m_extRow;
  84.     m_extRow = 0;
  85.     delete[] m_extPos;
  86.     m_extPos = 0;
  87. }
  88. Exec_query::~Exec_query()
  89. {
  90. }
  91. const Exec_query*
  92. Exec_query::getRawQuery() const
  93. {
  94.     ctx_assert(false);
  95.     return 0;
  96. }
  97. void
  98. Exec_query::bind(Ctx& ctx)
  99. {
  100.     const Code& code = getCode();
  101.     const SqlSpecs& sqlSpecs = code.sqlSpecs();
  102.     const unsigned count = sqlSpecs.count();
  103.     // read ARD
  104.     DescArea& ard = descArea(Desc_usage_ARD);
  105.     const unsigned ardCount = ard.getCount();
  106.     // create specification row
  107.     ExtSpecs extSpecs(count);
  108.     for (unsigned i = 1; i <= count; i++) {
  109. ExtType extType;
  110. if (i <= ardCount) {
  111.     OdbcData descData;
  112.     DescRec& rec = ard.getRecord(i);
  113.     // check for unbound column
  114.     rec.getField(ctx, SQL_DESC_DATA_PTR, descData);
  115.     SQLPOINTER desc_DATA_PTR = descData.type() != OdbcData::Undef ? descData.pointer() : 0;
  116.     if (desc_DATA_PTR == 0) {
  117. extType.setType(ctx, ExtType::Unbound);
  118.     } else {
  119. rec.getField(ctx, SQL_DESC_TYPE, descData);
  120. if (descData.type() == OdbcData::Undef) {
  121.     ctx.pushStatus(Error::Gen, "query column %u: external type not defined", i);
  122.     return;
  123. }
  124. SQLSMALLINT desc_TYPE = descData.smallint();
  125. if (desc_TYPE == SQL_C_DEFAULT) {
  126.     if (i <= code.m_sqlSpecs.count())
  127. desc_TYPE = code.m_sqlSpecs.getEntry(i).sqlType().sqlcdefault(ctx);
  128. }
  129. switch (desc_TYPE) {
  130. case SQL_C_CHAR:
  131. case SQL_C_BINARY:
  132. case SQL_C_SHORT: // for sun.jdbc.odbc
  133. case SQL_C_SSHORT:
  134. case SQL_C_USHORT:
  135. case SQL_C_LONG: // for sun.jdbc.odbc
  136. case SQL_C_SLONG:
  137. case SQL_C_ULONG:
  138. case SQL_C_SBIGINT:
  139. case SQL_C_UBIGINT:
  140. case SQL_C_FLOAT:
  141. case SQL_C_DOUBLE:
  142. case SQL_C_TYPE_TIMESTAMP:
  143.     break;
  144. default:
  145.     ctx.pushStatus(Error::Gen, "query column %u: unsupported external type %d", i, (int)desc_TYPE);
  146.     return;
  147. }
  148. extType.setType(ctx, static_cast<ExtType::Type>(desc_TYPE));
  149.     }
  150. } else {
  151.     extType.setType(ctx, ExtType::Unbound);
  152. }
  153. const ExtSpec extSpec(extType);
  154. extSpecs.setEntry(i, extSpec);
  155.     }
  156.     // create data row
  157.     ExtRow& extRow = *new ExtRow(extSpecs);
  158.     unsigned boundCount = 0;
  159.     for (unsigned i = 1; i <= count; i++) {
  160. const ExtSpec& extSpec = extSpecs.getEntry(i);
  161. if (extSpec.extType().type() != ExtType::Unbound) {
  162.     OdbcData descData;
  163.     DescRec& rec = ard.getRecord(i);
  164.     rec.getField(ctx, SQL_DESC_DATA_PTR, descData);
  165.     SQLPOINTER desc_DATA_PTR = descData.type() != OdbcData::Undef ? descData.pointer() : 0;
  166.     rec.getField(ctx, SQL_DESC_OCTET_LENGTH, descData);
  167.     SQLINTEGER desc_OCTET_LENGTH = descData.type() != OdbcData::Undef ? descData.integer() : 0;
  168.     rec.getField(ctx, SQL_DESC_INDICATOR_PTR, descData);
  169.     SQLINTEGER* desc_INDICATOR_PTR = descData.type() != OdbcData::Undef ? descData.integerPtr() : 0;
  170.     ctx_log4(("column %u: bind to 0x%x %d 0x%x", i, (unsigned)desc_DATA_PTR, (int)desc_OCTET_LENGTH, (unsigned)desc_INDICATOR_PTR));
  171.     ExtField extField(extSpec, desc_DATA_PTR, desc_OCTET_LENGTH, desc_INDICATOR_PTR, i);
  172.     extRow.setEntry(i, extField);
  173.     boundCount++;
  174. } else {
  175.     ExtField extField(extSpec, i);
  176.     extRow.setEntry(i, extField);
  177. }
  178.     }
  179.     Data& data = getData();
  180.     delete data.m_extRow;
  181.     data.m_extRow = &extRow;
  182.     ctx_log3(("bound %u out of %u columns", boundCount, count));
  183. }
  184. // execute and fetch
  185. void
  186. Exec_query::execute(Ctx& ctx, Ctl& ctl)
  187. {
  188.     Data& data = getData();
  189.     execImpl(ctx, ctl);
  190.     if (! ctx.ok())
  191. return;
  192.     data.initState();
  193.     if (m_topLevel) {
  194. stmtArea().setRowCount(ctx, data.getCount());
  195.     }
  196. }
  197. bool
  198. Exec_query::fetch(Ctx& ctx, Ctl& ctl)
  199. {
  200.     const Code& code = getCode();
  201.     Data& data = getData();
  202.     if (data.fetch(ctx, ctl)) {
  203. if (m_topLevel) {
  204.     stmtArea().setRowCount(ctx, data.getCount());
  205. }
  206. if (data.m_extRow != 0) {
  207.     data.sqlRow().copyout(ctx, *data.m_extRow);
  208.     if (! ctx.ok())
  209. return false;
  210. }
  211. if (data.m_extPos != 0) {
  212.     const unsigned count = code.sqlSpecs().count();
  213.     for (unsigned i = 0; i <= count; i++) {
  214. data.m_extPos[i] = 0;
  215.     }
  216. }
  217. return true;
  218.     }
  219.     if (m_topLevel) {
  220. stmtArea().setRowCount(ctx, data.getCount());
  221. if (ctx.ok()) {
  222.     ctx.setCode(SQL_NO_DATA);
  223. }
  224.     }
  225.     return false;
  226. }
  227. // odbc support
  228. void
  229. Exec_query::sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind)
  230. {
  231.     const Code& code = getCode();
  232.     Data& data = getData();
  233.     const SqlSpecs& sqlSpecs = code.m_sqlSpecs;
  234.     const unsigned count = sqlSpecs.count();
  235.     if (columnNumber == 0 || columnNumber > count) {
  236. ctx.pushStatus(Sqlstate::_07009, Error::Gen, "column index %u is not within 1 to %u", (unsigned)columnNumber, count);
  237. return;
  238.     }
  239.     // create positions array on first use
  240.     if (data.m_extPos == 0) {
  241. data.m_extPos = new int[1 + count];
  242. for (unsigned i = 0; i <= count; i++) {
  243.     data.m_extPos[i] = 0;
  244. }
  245.     }
  246.     if (targetType == SQL_ARD_TYPE) {
  247. // get type from ARD
  248. DescArea& ard = descArea(Desc_usage_ARD);
  249. const unsigned ardCount = ard.getCount();
  250. if (columnNumber <= ardCount) {
  251.     OdbcData descData;
  252.     DescRec& rec = ard.getRecord(columnNumber);
  253.     rec.getField(ctx, SQL_DESC_CONCISE_TYPE, descData);
  254.     if (descData.type() != OdbcData::Undef) {
  255. targetType = descData.smallint();
  256.     }
  257. }
  258. if (targetType == SQL_ARD_TYPE) {
  259.     ctx.pushStatus(Sqlstate::_07009, Error::Gen, "output column %u type not bound - cannot use SQL_ARD_TYPE", (unsigned)columnNumber);
  260.     return;
  261. }
  262.     }
  263.     ExtType extType;
  264.     if (targetValue != 0) {
  265. extType.setType(ctx, static_cast<ExtType::Type>(targetType));
  266. // check if supported
  267. if (! ctx.ok())
  268.     return;
  269.     } else {
  270. extType.setType(ctx, ExtType::Unbound);
  271.     }
  272.     ExtSpec extSpec(extType);
  273.     ExtField extField(extSpec, targetValue, bufferLength, strlen_or_Ind, columnNumber);
  274.     // copy out and update position
  275.     extField.setPos(data.m_extPos[columnNumber]);
  276.     const SqlRow& sqlRow = data.sqlRow();
  277.     const SqlField& sqlField = sqlRow.getEntry(columnNumber);
  278.     sqlField.copyout(ctx, extField);
  279.     data.m_extPos[columnNumber] = extField.getPos();
  280. }