HandleDesc.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/OdbcData.hpp>
  14. #include <common/DiagArea.hpp>
  15. #include <common/DataType.hpp>
  16. #include "HandleRoot.hpp"
  17. #include "HandleDbc.hpp"
  18. #include "HandleDesc.hpp"
  19. HandleDesc::HandleDesc(HandleDbc* pDbc) :
  20.     m_dbc(pDbc),
  21.     m_descArea(this, m_descSpec)
  22. {
  23. }
  24. HandleDesc::~HandleDesc()
  25. {
  26. }
  27. void
  28. HandleDesc::ctor(Ctx& ctx)
  29. {
  30. }
  31. void
  32. HandleDesc::dtor(Ctx& ctx)
  33. {
  34. }
  35. // allocate and free handles (no valid case)
  36. void
  37. HandleDesc::sqlAllocHandle(Ctx& ctx, SQLSMALLINT childType, HandleBase** ppChild)
  38. {
  39.     ctx.pushStatus(Sqlstate::_HY092, Error::Gen, "inappropriate handle type");
  40. }
  41. void
  42. HandleDesc::sqlFreeHandle(Ctx& ctx, SQLSMALLINT childType, HandleBase* ppChild)
  43. {
  44.     ctx.pushStatus(Sqlstate::_HY092, Error::Gen, "inappropriate handle type");
  45. }
  46. // set and get descriptor values
  47. void
  48. HandleDesc::sqlSetDescField(Ctx& ctx, SQLSMALLINT recNumber, SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength)
  49. {
  50.     const DescSpec& spec = m_descArea.findSpec(fieldIdentifier);
  51.     if (spec.m_pos == Desc_pos_end) {
  52. ctx.pushStatus(Sqlstate::_HY091, Error::Gen, "invalid descriptor id %d", (int)fieldIdentifier);
  53. return;
  54.     }
  55.     OdbcData data;
  56.     data.copyin(ctx, spec.m_type, value, bufferLength);
  57.     if (! ctx.ok())
  58. return;
  59.     const bool header = (spec.m_pos == Desc_pos_header);
  60.     const bool record = (spec.m_pos == Desc_pos_record);
  61.     ctx_assert(header || record);
  62.     DescArea& area = m_descArea;
  63.     if (header) {
  64. area.getHeader().setField(ctx, fieldIdentifier, data);
  65.     }
  66.     if (record) {
  67. if (recNumber < 0) {
  68.     ctx.pushStatus(Sqlstate::_07009, Error::Gen, "invalid record number %d", (int)recNumber);
  69.     return;
  70. }
  71. if (recNumber == 0) { // bookmark record
  72.     if (area.getUsage() == Desc_usage_IPD) {
  73. ctx.pushStatus(Sqlstate::_07009, Error::Gen, "cannot set bookmark IPD");
  74. return;
  75.     }
  76.     if (area.getUsage() == Desc_usage_APD) {
  77. ctx.pushStatus(Sqlstate::_07009, Error::Gen, "cannot set bookmark APD");
  78. return;
  79.     }
  80. }
  81. area.getRecord(recNumber).setField(ctx, fieldIdentifier, data);
  82.     }
  83. }
  84. void
  85. HandleDesc::sqlGetDescField(Ctx& ctx, SQLSMALLINT recNumber, SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* stringLength, SQLSMALLINT* stringLength2)
  86. {
  87.     const DescSpec& spec = m_descArea.findSpec(fieldIdentifier);
  88.     if (spec.m_pos == Desc_pos_end) {
  89. ctx.pushStatus(Sqlstate::_HY091, Error::Gen, "invalid descriptor id %d", (int)fieldIdentifier);
  90. return;
  91.     }
  92.     const bool header = (spec.m_pos == Desc_pos_header);
  93.     const bool record = (spec.m_pos == Desc_pos_record);
  94.     ctx_assert(header || record);
  95.     DescArea& area = m_descArea;
  96.     OdbcData data;
  97.     if (header) {
  98. area.getHeader().getField(ctx, fieldIdentifier, data);
  99. if (! ctx.ok())
  100.     return;
  101.     }
  102.     if (record) {
  103. if (recNumber < 0) {
  104.     ctx.pushStatus(Sqlstate::_07009, Error::Gen, "invalid record number %d", (int)recNumber);
  105.     return;
  106. }
  107. if (recNumber == 0) { // bookmark record
  108.     if (area.getUsage() == Desc_usage_IPD) {
  109. ctx.pushStatus(Sqlstate::_07009, Error::Gen, "cannot get bookmark IPD");
  110. return;
  111.     }
  112.     if (area.getUsage() == Desc_usage_IRD) {
  113. // XXX check SQL_ATTR_USE_BOOKMARK != SQL_UB_OFF
  114.     }
  115. }
  116. if ((unsigned)recNumber > area.getCount()) {
  117.     ctx.setCode(SQL_NO_DATA);
  118.     return;
  119. }
  120. area.getRecord(recNumber).getField(ctx, fieldIdentifier, data);
  121. if (! ctx.ok())
  122.     return;
  123.     }
  124.     // if no data, return success and undefined value
  125.     if (data.type() == OdbcData::Undef)
  126. return;
  127.     data.copyout(ctx, value, bufferLength, stringLength, stringLength2);
  128. }
  129. void
  130. HandleDesc::sqlColAttribute(Ctx& ctx, SQLUSMALLINT columnNumber, SQLUSMALLINT fieldIdentifier, SQLPOINTER characterAttribute, SQLSMALLINT bufferLength, SQLSMALLINT* stringLength, SQLPOINTER numericAttribute)
  131. {
  132.     ctx_log3(("sqlColAttribute col=%d id=%d", columnNumber, fieldIdentifier));
  133.     if (fieldIdentifier == SQL_COLUMN_LENGTH) { // XXX iODBC workaround
  134. fieldIdentifier = SQL_DESC_LENGTH;
  135.     }
  136.     if (fieldIdentifier == 1205 || fieldIdentifier == 1206) {
  137. ctx_log2(("ignore unknown OSQL fieldIdentifier %d", (int)fieldIdentifier));
  138. if (characterAttribute != 0)
  139.     *(char*)characterAttribute = 0;
  140. if (stringLength != 0)
  141.     *stringLength = 0;
  142. return;
  143.     }
  144.     const DescSpec& spec = m_descArea.findSpec(fieldIdentifier);
  145.     if (spec.m_pos == Desc_pos_end) {
  146. ctx.pushStatus(Sqlstate::_HY091, Error::Gen, "invalid descriptor id %d", (int)fieldIdentifier);
  147. return;
  148.     }
  149.     if (spec.m_type == OdbcData::Sqlchar || spec.m_type == OdbcData::Sqlstate)
  150. sqlGetDescField(ctx, columnNumber, fieldIdentifier, characterAttribute, bufferLength, 0, stringLength);
  151.     else {
  152. sqlGetDescField(ctx, columnNumber, fieldIdentifier, numericAttribute, -1, 0);
  153.     }
  154.     if (ctx.getCode() == SQL_NO_DATA) {
  155. ctx.setCode(SQL_SUCCESS);
  156. ctx.pushStatus(Sqlstate::_07009, Error::Gen, "invalid column number %d", (int)columnNumber);
  157.     }
  158. }
  159. void
  160. HandleDesc::sqlColAttributes(Ctx& ctx, SQLUSMALLINT icol, SQLUSMALLINT fdescType, SQLPOINTER rgbDesc, SQLSMALLINT cbDescMax, SQLSMALLINT* pcbDesc, SQLINTEGER* pfDesc)
  161. {
  162.     ctx_log3(("sqlColAttributes col=%hu id=%hu", icol, fdescType));
  163.     SQLUSMALLINT columnNumber = icol;
  164.     SQLUSMALLINT fieldIdentifier;
  165.     // XXX incomplete
  166.     if (fdescType == SQL_COLUMN_TYPE) {
  167. fieldIdentifier = SQL_DESC_TYPE;
  168.     } else if (fdescType == SQL_COLUMN_PRECISION) {
  169. SQLSMALLINT type;
  170. sqlGetDescField(ctx, columnNumber, SQL_DESC_TYPE, static_cast<SQLPOINTER>(&type), -1, 0);
  171. if (! ctx.ok())
  172.     return;
  173. switch (type) {
  174. case SQL_CHAR:
  175. case SQL_VARCHAR:
  176. case SQL_BINARY:
  177. case SQL_VARBINARY:
  178. case SQL_LONGVARCHAR:
  179. case SQL_LONGVARBINARY:
  180. case SQL_DATE:
  181.     fieldIdentifier = SQL_DESC_LENGTH;
  182.     break;
  183. default:
  184.     fieldIdentifier = SQL_DESC_PRECISION;
  185.     break;
  186. }
  187.     } else if (fdescType == SQL_COLUMN_SCALE) {
  188. SQLSMALLINT type;
  189. sqlGetDescField(ctx, columnNumber, SQL_DESC_TYPE, static_cast<SQLPOINTER>(&type), -1, 0);
  190. if (! ctx.ok())
  191.     return;
  192. switch (type) {
  193. default:
  194.     fieldIdentifier = SQL_DESC_SCALE;
  195.     break;
  196. }
  197.     } else if (fdescType == SQL_COLUMN_LENGTH) {
  198. SQLSMALLINT type;
  199. sqlGetDescField(ctx, columnNumber, SQL_DESC_TYPE, static_cast<SQLPOINTER>(&type), -1, 0);
  200. if (! ctx.ok())
  201.     return;
  202. switch (type) {
  203. default:
  204.     fieldIdentifier = SQL_DESC_LENGTH;
  205.     break;
  206. }
  207.     } else {
  208. fieldIdentifier = fdescType;
  209.     }
  210.     sqlColAttribute(ctx, columnNumber, fieldIdentifier, rgbDesc, cbDescMax, pcbDesc, pfDesc);
  211. }
  212. // set and get several common descriptor values
  213. void
  214. HandleDesc::sqlSetDescRec(Ctx& ctx, SQLSMALLINT recNumber, SQLSMALLINT type, SQLSMALLINT subType, SQLINTEGER length, SQLSMALLINT precision, SQLSMALLINT scale, SQLPOINTER data, SQLINTEGER* stringLength, SQLINTEGER* indicator)
  215. {
  216.     sqlSetDescField(ctx, recNumber, SQL_DESC_TYPE, reinterpret_cast<SQLPOINTER>(type), -1);
  217.     sqlSetDescField(ctx, recNumber, SQL_DESC_DATETIME_INTERVAL_CODE, reinterpret_cast<SQLPOINTER>(subType), -1);
  218.     sqlSetDescField(ctx, recNumber, SQL_DESC_OCTET_LENGTH, reinterpret_cast<SQLPOINTER>(length), -1);
  219.     sqlSetDescField(ctx, recNumber, SQL_DESC_PRECISION, reinterpret_cast<SQLPOINTER>(precision), -1);
  220.     sqlSetDescField(ctx, recNumber, SQL_DESC_SCALE, reinterpret_cast<SQLPOINTER>(scale), -1);
  221.     sqlSetDescField(ctx, recNumber, SQL_DESC_DATA_PTR, data, -1);
  222.     sqlSetDescField(ctx, recNumber, SQL_DESC_OCTET_LENGTH_PTR, reinterpret_cast<SQLPOINTER>(stringLength), -1);
  223.     sqlSetDescField(ctx, recNumber, SQL_DESC_INDICATOR_PTR, reinterpret_cast<SQLPOINTER>(indicator), -1);
  224. }
  225. void
  226. HandleDesc::sqlGetDescRec(Ctx& ctx, SQLSMALLINT recNumber, SQLCHAR* name, SQLSMALLINT bufferLength, SQLSMALLINT* stringLength, SQLSMALLINT* type, SQLSMALLINT* subType, SQLINTEGER* length, SQLSMALLINT* precision, SQLSMALLINT* scale, SQLSMALLINT* nullable)
  227. {
  228.     sqlGetDescField(ctx, recNumber, SQL_DESC_NAME, reinterpret_cast<SQLPOINTER>(name), bufferLength, 0, stringLength);
  229.     sqlGetDescField(ctx, recNumber, SQL_DESC_TYPE, reinterpret_cast<SQLPOINTER>(type), -1, 0);
  230.     sqlGetDescField(ctx, recNumber, SQL_DESC_DATETIME_INTERVAL_CODE, reinterpret_cast<SQLPOINTER>(subType), -1, 0);
  231.     sqlGetDescField(ctx, recNumber, SQL_DESC_OCTET_LENGTH, reinterpret_cast<SQLPOINTER>(length), -1, 0);
  232.     sqlGetDescField(ctx, recNumber, SQL_DESC_PRECISION, reinterpret_cast<SQLPOINTER>(precision), -1, 0);
  233.     sqlGetDescField(ctx, recNumber, SQL_DESC_SCALE, reinterpret_cast<SQLPOINTER>(scale), -1, 0);
  234.     sqlGetDescField(ctx, recNumber, SQL_DESC_NULLABLE, reinterpret_cast<SQLPOINTER>(nullable), -1, 0);
  235. }