transactd 2.4.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/CMakeLists.txt +1 -1
  3. data/README-JA.md +52 -529
  4. data/README.md +52 -523
  5. data/bin/common/tdclc_32_3_0.dll +0 -0
  6. data/bin/common/tdclc_64_3_0.dll +0 -0
  7. data/build/common/system.cmake +2 -1
  8. data/build/common/transactd_cl_common.cmake +3 -6
  9. data/build/swig/ruby/ruby.swg +85 -28
  10. data/build/swig/ruby/tdclrb_wrap.cpp +3195 -1578
  11. data/build/swig/tdcl.i +161 -5
  12. data/build/tdclc/CMakeLists.txt +1 -0
  13. data/build/tdclc/tdclc.cbproj +7 -1
  14. data/build/tdclc/tdclc.rc +4 -4
  15. data/build/tdclcpp/tdclcpp.rc +4 -4
  16. data/build/tdclcpp/tdclcpp_bc.cbproj +2 -5
  17. data/build/tdclrb/tdclrb.rc +4 -4
  18. data/source/bzs/db/blobStructs.h +1 -1
  19. data/source/bzs/db/engine/mysql/database.cpp +199 -74
  20. data/source/bzs/db/engine/mysql/database.h +47 -18
  21. data/source/bzs/db/engine/mysql/dbManager.cpp +1 -0
  22. data/source/bzs/db/engine/mysql/mysqlInternal.h +32 -8
  23. data/source/bzs/db/protocol/tdap/btrDate.cpp +110 -75
  24. data/source/bzs/db/protocol/tdap/btrDate.h +46 -21
  25. data/source/bzs/db/protocol/tdap/client/activeTable.cpp +18 -18
  26. data/source/bzs/db/protocol/tdap/client/activeTable.h +25 -25
  27. data/source/bzs/db/protocol/tdap/client/activeTableImple.h +10 -4
  28. data/source/bzs/db/protocol/tdap/client/client.cpp +6 -5
  29. data/source/bzs/db/protocol/tdap/client/client.h +82 -15
  30. data/source/bzs/db/protocol/tdap/client/database.cpp +531 -142
  31. data/source/bzs/db/protocol/tdap/client/database.h +19 -6
  32. data/source/bzs/db/protocol/tdap/client/dbDef.cpp +461 -408
  33. data/source/bzs/db/protocol/tdap/client/dbDef.h +11 -17
  34. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +61 -13
  35. data/source/bzs/db/protocol/tdap/client/field.cpp +1592 -1398
  36. data/source/bzs/db/protocol/tdap/client/field.h +110 -121
  37. data/source/bzs/db/protocol/tdap/client/fields.h +40 -10
  38. data/source/bzs/db/protocol/tdap/client/filter.h +69 -55
  39. data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +296 -164
  40. data/source/bzs/db/protocol/tdap/client/groupQuery.h +77 -25
  41. data/source/bzs/db/protocol/tdap/client/memRecord.cpp +31 -13
  42. data/source/bzs/db/protocol/tdap/client/memRecord.h +31 -21
  43. data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +1 -1
  44. data/source/bzs/db/protocol/tdap/client/nsDatabase.h +4 -1
  45. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +69 -24
  46. data/source/bzs/db/protocol/tdap/client/nsTable.h +3 -1
  47. data/source/bzs/db/protocol/tdap/client/recordset.cpp +1 -0
  48. data/source/bzs/db/protocol/tdap/client/recordsetImple.h +46 -27
  49. data/source/bzs/db/protocol/tdap/client/request.h +2 -1
  50. data/source/bzs/db/protocol/tdap/client/serializer.cpp +44 -9
  51. data/source/bzs/db/protocol/tdap/client/serializer.h +1 -1
  52. data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +182 -76
  53. data/source/bzs/db/protocol/tdap/client/sqlBuilder.h +23 -12
  54. data/source/bzs/db/protocol/tdap/client/stringConverter.h +8 -10
  55. data/source/bzs/db/protocol/tdap/client/table.cpp +172 -93
  56. data/source/bzs/db/protocol/tdap/client/table.h +112 -37
  57. data/source/bzs/db/protocol/tdap/client/trdboostapi.h +17 -0
  58. data/source/bzs/db/protocol/tdap/client/trdboostapiInternal.h +0 -1
  59. data/source/bzs/db/protocol/tdap/client/trdclcppautolink.h +0 -2
  60. data/source/bzs/db/protocol/tdap/client/trdormapi.h +1 -1
  61. data/source/bzs/db/protocol/tdap/fieldComp.h +698 -14
  62. data/source/bzs/db/protocol/tdap/myDateTime.cpp +723 -307
  63. data/source/bzs/db/protocol/tdap/myDateTime.h +294 -0
  64. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +164 -54
  65. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.h +6 -3
  66. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +133 -550
  67. data/source/bzs/db/protocol/tdap/mysql/request.h +6 -5
  68. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +217 -82
  69. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +1 -1
  70. data/source/bzs/db/protocol/tdap/tdapRequest.h +4 -9
  71. data/source/bzs/db/protocol/tdap/tdapSchema.cpp +808 -17
  72. data/source/bzs/db/protocol/tdap/tdapSchema.h +656 -164
  73. data/source/bzs/db/protocol/tdap/tdapcapi.h +130 -28
  74. data/source/bzs/db/protocol/tdap/uri.h +40 -32
  75. data/source/bzs/db/transactd/connManager.cpp +1 -1
  76. data/source/bzs/db/transactd/transactd.cpp +7 -0
  77. data/source/bzs/env/compiler.h +107 -94
  78. data/source/bzs/env/crosscompile.cpp +24 -12
  79. data/source/bzs/env/crosscompile.h +75 -6
  80. data/source/bzs/env/mbcswchrLinux.cpp +2 -2
  81. data/source/bzs/env/tcharMinGW.h +4 -0
  82. data/source/bzs/example/changeSchema.cpp +22 -17
  83. data/source/bzs/example/queryData.cpp +4 -0
  84. data/source/bzs/netsvc/client/iconnection.h +3 -1
  85. data/source/bzs/netsvc/client/tcpClient.h +10 -3
  86. data/source/bzs/rtl/stringBuffers.cpp +7 -0
  87. data/source/bzs/test/tdclatl/bench_query_atl.js +6 -0
  88. data/source/bzs/test/tdclatl/bench_tdclatl.js +8 -1
  89. data/source/bzs/test/tdclatl/test_query_atl.js +22 -2
  90. data/source/bzs/test/tdclatl/test_v3.js +1017 -0
  91. data/source/bzs/test/tdclphp/transactd_Test.php +55 -21
  92. data/source/bzs/test/tdclphp/transactd_datetime_Test.php +0 -5
  93. data/source/bzs/test/tdclphp/transactd_pool_Test.php +2 -0
  94. data/source/bzs/test/tdclphp/transactd_v3_Test.php +743 -0
  95. data/source/bzs/test/tdclrb/transactd_datetime_spec.rb +0 -5
  96. data/source/bzs/test/tdclrb/transactd_pool_spec.rb +2 -0
  97. data/source/bzs/test/tdclrb/transactd_spec.rb +39 -16
  98. data/source/bzs/test/tdclrb/transactd_v3_spec.rb +748 -0
  99. data/source/bzs/test/transactdBench/transactdBench.cpp +55 -58
  100. data/source/bzs/test/transactdBench/transactdBench2.cpp +1 -3
  101. data/source/bzs/test/trdclengn/testField.h +3305 -0
  102. data/source/bzs/test/trdclengn/test_tdclcpp_v3.cpp +1050 -0
  103. data/source/bzs/test/trdclengn/test_trdclengn.cpp +112 -190
  104. data/source/bzs/test/trdclengn/testbase.h +137 -0
  105. data/source/global/ormsrcgen/srcgen.cpp +23 -12
  106. data/source/global/ormsrcgen/template/ormDataClass_template.h +2 -0
  107. data/source/global/querystmts/querystmts.cpp +2 -3
  108. data/source/global/tdclatl/Bitset.cpp +38 -0
  109. data/source/global/tdclatl/Bitset.h +63 -0
  110. data/source/global/tdclatl/Database.cpp +59 -18
  111. data/source/global/tdclatl/Database.h +7 -4
  112. data/source/global/tdclatl/DbDef.cpp +6 -6
  113. data/source/global/tdclatl/DbDef.h +2 -1
  114. data/source/global/tdclatl/Field.cpp +112 -0
  115. data/source/global/tdclatl/Field.h +19 -5
  116. data/source/global/tdclatl/FieldDef.cpp +137 -16
  117. data/source/global/tdclatl/FieldDef.h +18 -2
  118. data/source/global/tdclatl/FieldDefs.cpp +54 -1
  119. data/source/global/tdclatl/FieldDefs.h +3 -0
  120. data/source/global/tdclatl/GroupQuery.cpp +8 -8
  121. data/source/global/tdclatl/QueryBase.cpp +65 -0
  122. data/source/global/tdclatl/QueryBase.h +10 -0
  123. data/source/global/tdclatl/Record.cpp +33 -2
  124. data/source/global/tdclatl/Record.h +3 -1
  125. data/source/global/tdclatl/RecordsetQuery.cpp +42 -0
  126. data/source/global/tdclatl/RecordsetQuery.h +8 -0
  127. data/source/global/tdclatl/Table.cpp +127 -3
  128. data/source/global/tdclatl/Table.h +10 -1
  129. data/source/global/tdclatl/TableDef.cpp +41 -8
  130. data/source/global/tdclatl/TableDef.h +7 -2
  131. data/source/global/tdclatl/activeTable.cpp +40 -71
  132. data/source/global/tdclatl/resource.h +0 -0
  133. data/source/global/tdclatl/tdclatl.idl +222 -28
  134. data/source/linux/tchar.h +100 -96
  135. data/transactd.gemspec +2 -2
  136. metadata +13 -11
  137. data/BUILD_UNIX-JA.md +0 -161
  138. data/BUILD_WIN-JA.md +0 -326
  139. data/README_ORMSRCGEN-JA.md +0 -115
  140. data/README_ORMSRCGEN.md +0 -118
  141. data/RELEASE_NOTE-JA.md +0 -356
  142. data/RELEASE_NOTE.md +0 -360
  143. data/bin/common/tdclc_32_2_4.dll +0 -0
  144. data/bin/common/tdclc_64_2_4.dll +0 -0
  145. data/source/bzs/test/trdclengn/test_blob.cpp +0 -375
@@ -1,5 +1,5 @@
1
1
  /*=================================================================
2
- Copyright (C) 2014 BizStation Corp All rights reserved.
2
+ Copyright (C) 2014,2015 BizStation Corp All rights reserved.
3
3
 
4
4
  This program is free software; you can redistribute it and/or
5
5
  modify it under the terms of the GNU General Public License
@@ -17,10 +17,13 @@
17
17
  02111-1307, USA.
18
18
  =================================================================*/
19
19
  #pragma hdrstop
20
+ #pragma warning(disable : 4996)
20
21
  #include "groupQuery.h"
21
22
  #include "recordsetImple.h"
22
23
  #include "filter.h"
24
+ #include <bzs/db/protocol/tdap/fieldComp.h>
23
25
  #include <boost/algorithm/string.hpp>
26
+ #pragma warning(default : 4996)
24
27
 
25
28
  #pragma package(smart_init)
26
29
 
@@ -38,12 +41,20 @@ namespace client
38
41
  // ---------------------------------------------------------------------------
39
42
  // struct fieldNamesImple
40
43
  // ---------------------------------------------------------------------------
44
+ struct valueItem
45
+ {
46
+ std::_tstring value;
47
+ bool null;
48
+ };
49
+
41
50
  struct fieldNamesImple
42
51
  {
43
- std::vector<std::_tstring> keyFields;
52
+ std::vector<valueItem> keyFields;
44
53
  fieldNamesImple() {}
45
54
  };
46
55
 
56
+
57
+
47
58
  // ---------------------------------------------------------------------------
48
59
  // class fieldNames
49
60
  // ---------------------------------------------------------------------------
@@ -87,6 +98,14 @@ fieldNames& fieldNames::reset()
87
98
  return *this;
88
99
  }
89
100
 
101
+ void fieldNames::doAddValue(const _TCHAR* v, bool isNull)
102
+ {
103
+ valueItem itm;
104
+ itm.value = v;
105
+ itm.null = isNull;
106
+ m_impl->keyFields.push_back(itm);
107
+ }
108
+
90
109
  fieldNames& fieldNames::keyField(const _TCHAR* name, const _TCHAR* name1,
91
110
  const _TCHAR* name2, const _TCHAR* name3,
92
111
  const _TCHAR* name4, const _TCHAR* name5,
@@ -96,27 +115,49 @@ fieldNames& fieldNames::keyField(const _TCHAR* name, const _TCHAR* name1,
96
115
  {
97
116
  m_impl->keyFields.clear();
98
117
  if (name)
99
- m_impl->keyFields.push_back(name);
100
- if (name1)
101
- m_impl->keyFields.push_back(name1);
102
- if (name2)
103
- m_impl->keyFields.push_back(name2);
104
- if (name3)
105
- m_impl->keyFields.push_back(name3);
106
- if (name4)
107
- m_impl->keyFields.push_back(name4);
108
- if (name5)
109
- m_impl->keyFields.push_back(name5);
110
- if (name6)
111
- m_impl->keyFields.push_back(name6);
112
- if (name7)
113
- m_impl->keyFields.push_back(name7);
114
- if (name8)
115
- m_impl->keyFields.push_back(name8);
116
- if (name9)
117
- m_impl->keyFields.push_back(name9);
118
- if (name10)
119
- m_impl->keyFields.push_back(name10);
118
+ {
119
+ doAddValue(name, false);
120
+ if (name1)
121
+ {
122
+ doAddValue(name1, false);
123
+ if (name2)
124
+ {
125
+ doAddValue(name2, false);
126
+ if (name3)
127
+ {
128
+ doAddValue(name3, false);
129
+ if (name4)
130
+ {
131
+ doAddValue(name4, false);
132
+ {
133
+ if (name5)
134
+ {
135
+ doAddValue(name5, false);
136
+ if (name6)
137
+ {
138
+ doAddValue(name6, false);
139
+ if (name7)
140
+ {
141
+ doAddValue(name7, false);
142
+ if (name8)
143
+ {
144
+ doAddValue(name8, false);
145
+ if (name9)
146
+ {
147
+ doAddValue(name9, false);
148
+ if (name10)
149
+ doAddValue(name10, false);
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
120
161
  return *this;
121
162
  }
122
163
 
@@ -128,25 +169,63 @@ int fieldNames::count() const
128
169
  const _TCHAR* fieldNames::getValue(int index) const
129
170
  {
130
171
  assert(index >= 0 && index < count());
131
- return m_impl->keyFields[index].c_str();
172
+ return m_impl->keyFields[index].value.c_str();
132
173
  }
133
174
 
134
175
  const _TCHAR* fieldNames::operator[](int index) const
135
176
  {
136
177
  assert(index >= 0 && index < count());
137
- return m_impl->keyFields[index].c_str();
178
+ return m_impl->keyFields[index].value.c_str();
138
179
  }
139
180
 
140
181
  void fieldNames::addValue(const _TCHAR* v)
141
182
  {
142
- m_impl->keyFields.push_back(v);
183
+ doAddValue(v, false);
143
184
  }
144
185
 
145
186
  void fieldNames::addValues(const _TCHAR* values, const _TCHAR* delmi)
146
187
  {
147
- boost::algorithm::split(m_impl->keyFields, values, boost::is_any_of(delmi));
188
+ std::vector<std::_tstring> tmp;
189
+ boost::algorithm::split(tmp, values, boost::is_any_of(delmi));
190
+ valueItem itm;
191
+ itm.null = false;
192
+ for (int i=0;i < (int)tmp.size(); ++i)
193
+ {
194
+ itm.value = tmp[i];
195
+ m_impl->keyFields.push_back(itm);
196
+ }
197
+
198
+ }
199
+
200
+ // ---------------------------------------------------------------------------
201
+ // class fieldValues
202
+ // ---------------------------------------------------------------------------
203
+ fieldValues::fieldValues() : fieldNames() {}
204
+
205
+ fieldValues::fieldValues(const fieldValues& r): fieldNames(r) {}
206
+
207
+ fieldValues& fieldValues::operator=(const fieldValues& r)
208
+ {
209
+ if (this != &r)
210
+ {
211
+ fieldNames::operator=(r);
212
+ }
213
+ return *this;
214
+ }
215
+
216
+ void fieldValues::addValue(const _TCHAR* v, bool isNull)
217
+ {
218
+ doAddValue(v, isNull);
148
219
  }
149
220
 
221
+ bool fieldValues::isNull(int index) const
222
+ {
223
+ assert(index >= 0 && index < count());
224
+ return m_impl->keyFields[index].null;
225
+
226
+ }
227
+
228
+
150
229
  // ---------------------------------------------------------------------------
151
230
  // struct recordsetQueryImple
152
231
  // ---------------------------------------------------------------------------
@@ -155,18 +234,25 @@ struct recordsetQueryImple
155
234
  row_ptr row;
156
235
  struct compItem
157
236
  {
158
- compFieldFunc compFunc;
237
+ judgeFunc isMatchFunc;
238
+ comp1Func compFunc;
159
239
  short index;
160
- unsigned char compType;
240
+ uchar_td compType;
161
241
  char combine;
242
+ struct
243
+ {
244
+ bool nullable : 1;
245
+ bool nulllog : 1;
246
+ };
162
247
  };
163
248
  std::vector<compItem> compItems;
164
-
165
- short endIndex;
166
249
  fielddefs compFields;
167
- recordsetQueryImple() : row(NULL) {}
250
+ short endIndex;
251
+ bool mysqlnull;
252
+
253
+ recordsetQueryImple() : row(NULL),mysqlnull(false) {}
168
254
  recordsetQueryImple(const recordsetQueryImple& r)
169
- : row(r.row), compItems(r.compItems), compFields(r.compFields)
255
+ : row(r.row), compItems(r.compItems), compFields(r.compFields), mysqlnull(r.mysqlnull)
170
256
  {
171
257
  if (row)
172
258
  row->addref();
@@ -219,6 +305,7 @@ recordsetQuery::~recordsetQuery()
219
305
 
220
306
  void recordsetQuery::init(const fielddefs* fdinfo)
221
307
  {
308
+ m_imple->mysqlnull = fdinfo->mysqlnullEnable();
222
309
  const std::vector<std::_tstring>& tokns = getWheres();
223
310
  m_imple->compFields.clear();
224
311
  m_imple->compItems.clear();
@@ -226,9 +313,12 @@ void recordsetQuery::init(const fielddefs* fdinfo)
226
313
  {
227
314
  recordsetQueryImple::compItem itm;
228
315
  itm.index = fdinfo->indexByName(tokns[i].c_str());
316
+ if (itm.index >= 0)
317
+ itm.nullable = (*fdinfo)[itm.index].isNullable();
229
318
  m_imple->compItems.push_back(itm);
230
- m_imple->compFields.push_back(&((*fdinfo)[itm.index]), true /*rePosition*/);
319
+ m_imple->compFields.push_back(&((*fdinfo)[itm.index]));
231
320
  }
321
+ m_imple->compFields.calcFieldPos(0 /*startIndex*/, true);
232
322
  m_imple->row = memoryRecord::create(m_imple->compFields);
233
323
  m_imple->row->addref();
234
324
  m_imple->row->setRecordData(autoMemory::create(), 0, 0, &m_imple->endIndex, true);
@@ -241,16 +331,23 @@ void recordsetQuery::init(const fielddefs* fdinfo)
241
331
  fd = tokns[i + 2].c_str();
242
332
  bool part = fd.isCompPartAndMakeValue();
243
333
  itm.compType = getFilterLogicTypeCode(tokns[i + 1].c_str());
334
+ eCompType log = (eCompType)(itm.compType & 0xf);
335
+ itm.nulllog = ((log == eIsNull) || (log == eIsNotNull));
244
336
  if (!part)
245
337
  itm.compType |= CMPLOGICAL_VAR_COMP_ALL;
246
338
  fielddef& fdd = const_cast<fielddef&>(m_imple->compFields[index]);
247
- fdd.len = compDataLen(m_imple->compFields[index],
248
- (const uchar_td*)fd.ptr(), part);
249
- itm.compFunc = fd.getCompFunc(itm.compType);
339
+ fdd.len = m_imple->compFields[index].compDataLen((const uchar_td*)fd.ptr(), part);
340
+ uchar_td type = fdd.type;
341
+ if (fdd.isLegacyTimeFormat())
342
+ {
343
+ if (type == ft_mytime) type = ft_mytime_num_cmp;
344
+ if (type == ft_mydatetime) type = ft_mydatetime_num_cmp;
345
+ if (type == ft_mytimestamp) type = ft_mytimestamp_num_cmp;
346
+ }
250
347
 
251
- // When use wide string functions, len convert to wide char num.
252
- if ((itm.compFunc == compiWString) || (itm.compFunc == compWString))
253
- fdd.len /= sizeof(char16_t);
348
+ itm.compFunc = getCompFunc(type, fdd.len, itm.compType,
349
+ fdd.varLenBytes() + fdd.blobLenBytes());
350
+ itm.isMatchFunc = getJudgeFunc((eCompType)itm.compType);
254
351
 
255
352
  if (i + 3 < (int)tokns.size())
256
353
  {
@@ -266,44 +363,22 @@ void recordsetQuery::init(const fielddefs* fdinfo)
266
363
  }
267
364
  }
268
365
 
269
- bool recordsetQuery::isMatch(int ret, unsigned char compType) const
270
- {
271
- compType &= 0xf; // lower than 15
272
- switch ((eCompType)compType)
273
- {
274
- case eEqual:
275
- case eBitAnd:
276
- return (ret == 0);
277
- case eGreaterEq:
278
- return (ret >= 0);
279
- case eLessEq:
280
- return (ret <= 0);
281
- case eGreater:
282
- return (ret > 0);
283
- case eLess:
284
- return (ret < 0);
285
- case eNotEq:
286
- case eNotBitAnd:
287
- return (ret != 0);
288
- }
289
- return false;
290
- }
291
-
292
366
  bool recordsetQuery::match(const row_ptr row) const
293
367
  {
294
368
  for (int i = 0; i < (int)m_imple->compItems.size(); ++i)
295
369
  {
296
370
  recordsetQueryImple::compItem& itm = m_imple->compItems[i];
297
- bool ret = isMatch(
298
- itm.compFunc((*row)[itm.index], (*m_imple->row)[i], itm.compType)
299
- ,itm.compType);
300
-
301
- if (itm.combine == eCend)
302
- return ret;
303
- if (ret && itm.combine == eCor)
304
- return true;
305
- if (!ret && itm.combine == eCand)
306
- return false;
371
+ bool ret;
372
+ int nullJudge = 2;
373
+ const field& f = (*row)[itm.index];
374
+ if (m_imple->mysqlnull && (itm.nullable || itm.nulllog))
375
+ nullJudge = f.nullComp((eCompType)(itm.compType & 0xf));
376
+ if (nullJudge < 2)
377
+ ret = (nullJudge == 0) ? true : false;
378
+ else
379
+ ret = itm.isMatchFunc(itm.compFunc((const char*)f.ptr(), (const char*)((*m_imple->row)[i].ptr()), (*m_imple->row)[i].len()));
380
+
381
+ if (isEndComp(itm.combine, ret)) return ret;
307
382
  }
308
383
  assert(0);
309
384
  return false;
@@ -330,7 +405,7 @@ class groupQueryImple : public fieldNames
330
405
  bool enabled = false;
331
406
  for (int j = 0; j < (int)m_impl->keyFields.size(); ++j)
332
407
  {
333
- if (m_impl->keyFields[j] == fds[i].name())
408
+ if (m_impl->keyFields[j].value == fds[i].name())
334
409
  {
335
410
  enabled = true;
336
411
  break;
@@ -386,17 +461,16 @@ public:
386
461
  std::vector<recordsetImple::key_type> keyFields;
387
462
 
388
463
  for (int i = 0; i < (int)m_impl->keyFields.size(); ++i)
389
- keyFields.push_back(resolvKeyValue(mdls, m_impl->keyFields[i]));
464
+ keyFields.push_back(resolvKeyValue(mdls, m_impl->keyFields[i].value));
390
465
 
391
466
  for (int i = 0; i < (int)m_funcs.size(); ++i)
392
467
  {
393
-
394
468
  groupFuncBase* f = m_funcs[i];
395
469
  f->init(mdls.fieldDefs());
396
470
 
397
471
  if (f->resultKey() == (int)mdls.fieldDefs()->size())
398
472
  mdls.appendField(f->resultName(), f->resultType(),
399
- f->resultLen());
473
+ f->resultLen(), f->decimals());
400
474
  }
401
475
 
402
476
  grouping_comp<recordsetImple> groupingComp(mdls, keyFields);
@@ -407,8 +481,7 @@ public:
407
481
  while (it != ite)
408
482
  {
409
483
  bool found = false;
410
- i = binary_search(n, index, 0, (int)index.size(), groupingComp,
411
- found);
484
+ i = binary_search(n, index, 0, (int)index.size(), groupingComp, found);
412
485
  if (!found)
413
486
  index.insert(index.begin() + i, n);
414
487
  for (int j = 0; j < (int)m_funcs.size(); ++j)
@@ -428,12 +501,13 @@ public:
428
501
 
429
502
  for (int j = 0; j < (int)m_funcs.size(); ++j)
430
503
  {
431
- if (m_funcs[j]->resultType() == ft_float)
504
+ if (m_funcs[j]->isNull(i))
505
+ (*cur).setInvalidMemblock(m_funcs[j]->resultKey());
506
+ else if (m_funcs[j]->resultType() == ft_float)
432
507
  setValue(cur, m_funcs[j]->resultKey(), m_funcs[j]->numericResult(i));
433
508
  else
434
509
  memcpy((*cur)[m_funcs[j]->resultKey()].ptr() ,
435
- m_funcs[j]->stringResult(i),
436
- m_funcs[j]->resultLen());
510
+ m_funcs[j]->stringResult(i), m_funcs[j]->resultLen());
437
511
  }
438
512
  mdls.push_back(cur);
439
513
  }
@@ -534,10 +608,12 @@ private:
534
608
  friend class groupQueryImple;
535
609
  fieldNames m_targetNames;
536
610
  std::_tstring m_resultName;
537
- int m_resultKey;
538
611
  std::vector<int> m_targetKeys;
612
+ int m_resultKey;
539
613
  ushort_td m_resultLen;
540
614
  uchar_td m_resultType;
615
+ uchar_td m_decimals;
616
+ bool m_insertFlag;
541
617
  void clearStrings()
542
618
  {
543
619
  std::vector<unsigned char*>::iterator it = m_strings.begin();
@@ -561,33 +637,32 @@ public:
561
637
  std::vector<groupFuncBase::numeric_type> m_values;
562
638
  std::vector<__int64> m_counts;
563
639
  std::vector<unsigned char*> m_strings;
640
+ std::vector<bool> m_nulls;
564
641
 
565
642
  inline groupFuncBaseImple() : m_resultKey(-1),
566
- m_resultLen(sizeof(double)),
567
- m_resultType(ft_float)
643
+ m_resultLen(sizeof(double)), m_resultType(ft_float),
644
+ m_decimals(0)
645
+
568
646
  {
569
647
  }
570
648
 
571
- inline groupFuncBaseImple(const fieldNames& targetNames,
572
- const _TCHAR* resultName = NULL)
573
- : m_resultKey(-1),
574
- m_resultLen(sizeof(double)),
575
- m_resultType(ft_float)
649
+ inline groupFuncBaseImple(const fieldNames& targetNames, const _TCHAR* resultName = NULL)
650
+ : m_resultKey(-1), m_resultLen(sizeof(double)), m_resultType(ft_float), m_decimals(0)
651
+
576
652
  {
577
653
  m_targetNames = targetNames;
578
654
  m_resultName = (m_targetNames.count() &&
579
655
  ((resultName == NULL) || resultName[0] == 0x00))
580
- ? targetNames[0]
581
- : resultName;
656
+ ? targetNames[0] : resultName;
582
657
  }
583
658
 
584
659
  inline groupFuncBaseImple(const groupFuncBaseImple& r)
585
660
  : m_targetNames(r.m_targetNames), m_resultName(r.m_resultName),
586
661
  m_resultKey(r.m_resultKey),
587
- m_resultLen(r.m_resultLen), m_resultType(r.m_resultType),
588
- m_values(r.m_values), m_counts(r.m_counts)
662
+ m_resultLen(r.m_resultLen), m_resultType(r.m_resultType), m_decimals(r.m_decimals),
663
+ m_values(r.m_values), m_counts(r.m_counts),m_nulls(r.m_nulls)
589
664
  {
590
- copyStrings(r.m_strings);
665
+ copyStrings(r.m_strings);
591
666
  }
592
667
 
593
668
  groupFuncBaseImple& operator=(const groupFuncBaseImple& r)
@@ -599,8 +674,10 @@ public:
599
674
  m_resultKey = r.m_resultKey;
600
675
  m_resultType = r.m_resultType;
601
676
  m_resultLen = r.m_resultLen;
677
+ m_decimals = r.m_decimals;
602
678
  m_values = r.m_values;
603
679
  m_counts = r.m_counts;
680
+ m_nulls = r.m_nulls;
604
681
  m_strings.clear();
605
682
  copyStrings(r.m_strings);
606
683
  }
@@ -618,9 +695,9 @@ public:
618
695
  m_resultLen = len;
619
696
  }
620
697
 
621
- inline uchar_td resultType() { return m_resultType; }
698
+ inline uchar_td resultType() const { return m_resultType; }
622
699
 
623
- inline ushort_td resultLen() { return m_resultLen; }
700
+ inline ushort_td resultLen() const { return m_resultLen; }
624
701
 
625
702
  inline void appendStringBuffer(int index)
626
703
  {
@@ -643,15 +720,26 @@ public:
643
720
  }
644
721
  else
645
722
  appendStringBuffer(index);
723
+ std::vector<bool>::iterator it = m_nulls.begin();
724
+ if (index)
725
+ it += index;
726
+ m_nulls.insert(it, true);
727
+ m_insertFlag = true;
646
728
  }
647
729
 
648
730
  inline void init(const fielddefs* fdinfo)
649
731
  {
650
732
  m_targetKeys.clear();
651
733
  for (int i = 0; i < m_targetNames.count(); ++i)
652
- m_targetKeys.push_back((m_targetNames[i][0] != 0x00)
653
- ? fdinfo->indexByName(m_targetNames[i])
654
- : -1);
734
+ {
735
+ int index = (m_targetNames[i][0] != 0x00)
736
+ ? fdinfo->indexByName(m_targetNames[i]) : -1;
737
+ m_targetKeys.push_back(index);
738
+
739
+ //Auto set decimals
740
+ if (index != -1)
741
+ m_decimals = std::max<uchar_td>(m_decimals, (*fdinfo)[index].decimals);
742
+ }
655
743
  m_resultKey = fdinfo->indexByName(m_resultName);
656
744
  if (m_resultKey == -1)
657
745
  m_resultKey = (int)fdinfo->size();
@@ -687,6 +775,15 @@ public:
687
775
  }
688
776
 
689
777
  inline int targetKeys() const { return (int)m_targetKeys.size(); }
778
+
779
+ inline bool insertFlag() const { return m_insertFlag; }
780
+
781
+ inline void clearFlag() { m_insertFlag = false;}
782
+
783
+ inline void setDecimals(uchar_td v) { m_decimals = v; }
784
+
785
+ inline uchar_td decimals() const { return m_decimals; }
786
+
690
787
  };
691
788
 
692
789
  // ---------------------------------------------------------------------------
@@ -727,10 +824,6 @@ void groupFuncBase::initResultVariable(int index)
727
824
  m_imple->initResultVariable(index);
728
825
  }
729
826
 
730
- void groupFuncBase::doCalc(const row_ptr& row, int groupIndex)
731
- {
732
- }
733
-
734
827
  void groupFuncBase::doInit(const fielddefs* fdinfo)
735
828
  {
736
829
  if (whereTokens() != 0)
@@ -744,6 +837,16 @@ void groupFuncBase::init(const fielddefs* fdinfo)
744
837
  doInit(fdinfo);
745
838
  }
746
839
 
840
+ bool groupFuncBase::insertFlag() const
841
+ {
842
+ return m_imple->insertFlag();
843
+ }
844
+
845
+ void groupFuncBase::clearInsertFlag()
846
+ {
847
+ m_imple->clearFlag();
848
+ }
849
+
747
850
  groupFuncBase& groupFuncBase::operator=(const recordsetQuery& v)
748
851
  {
749
852
  recordsetQuery::operator=(v);
@@ -770,6 +873,11 @@ int groupFuncBase::resultKey() const
770
873
  return m_imple->resultKey();
771
874
  }
772
875
 
876
+ bool groupFuncBase::isNull(int index) const
877
+ {
878
+ return m_imple->m_nulls[index];
879
+ }
880
+
773
881
  void groupFuncBase::reset()
774
882
  {
775
883
  recordsetQuery::reset();
@@ -781,10 +889,25 @@ void groupFuncBase::doReset()
781
889
  m_imple->reset();
782
890
  }
783
891
 
892
+ void groupFuncBase::doCalcEachkey(const field& fd, int index) {}
893
+
894
+ void groupFuncBase::doCalc(const row_ptr& row, int index)
895
+ {
896
+ for (int i = 0; i < m_imple->targetKeys(); ++i)
897
+ {
898
+ const field& fd = (*row)[m_imple->targetKey(i)];
899
+ if (!fd.isNull())
900
+ {
901
+ doCalcEachkey(fd, index);
902
+ m_imple->m_nulls[index] = false;
903
+ }
904
+ }
905
+ }
906
+
784
907
  void groupFuncBase::operator()(const row_ptr& row, int index, bool insert)
785
908
  {
786
909
  if (insert)
787
- initResultVariable(index); // setNullValue
910
+ initResultVariable(index);
788
911
  bool flag = (whereTokens() == 0);
789
912
 
790
913
  if (!flag)
@@ -813,6 +936,8 @@ uchar_td groupFuncBase::resultType() const
813
936
  return m_imple->resultType();
814
937
  }
815
938
 
939
+ uchar_td groupFuncBase::decimals() const { return m_imple->decimals();}
940
+
816
941
  // ---------------------------------------------------------------------------
817
942
  // class sum
818
943
  // ---------------------------------------------------------------------------
@@ -826,12 +951,10 @@ sum::sum(const fieldNames& targetNames, const _TCHAR* resultName)
826
951
  {
827
952
  }
828
953
 
829
- void sum::doCalc(const row_ptr& row, int index)
954
+ void sum::doCalcEachkey(const field& fd, int index)
830
955
  {
831
956
  numeric_type tmp = 0;
832
- for (int i = 0; i < m_imple->targetKeys(); ++i)
833
- m_imple->m_values[index] +=
834
- fieldValue((*row)[m_imple->targetKey(i)], tmp);
957
+ m_imple->m_values[index] += fieldValue(fd, tmp);
835
958
  }
836
959
 
837
960
  groupFuncBase* sum::clone()
@@ -849,16 +972,38 @@ count* count::create(const _TCHAR* resultName)
849
972
  return new count(resultName);
850
973
  }
851
974
 
975
+ count* count::create(const fieldNames& targetNames, const _TCHAR* resultName)
976
+ {
977
+ return new count(targetNames, resultName);
978
+ }
979
+
852
980
  count::count(const _TCHAR* resultName) : groupFuncBase()
853
981
  {
854
982
  setResultName(resultName);
855
983
  }
856
984
 
857
- void count::doCalc(const row_ptr& row, int index)
985
+ count::count(const fieldNames& targetNames, const _TCHAR* resultName)
986
+ : groupFuncBase(targetNames, resultName) {}
987
+
988
+ void count::initResultVariable(int index)
989
+ {
990
+ groupFuncBase::initResultVariable(index);
991
+ m_imple->m_nulls[index] = false;
992
+ }
993
+
994
+ void count::doCalcEachkey(const field& fd, int index)
858
995
  {
859
996
  m_imple->m_values[index] = m_imple->m_values[index] + 1;
860
997
  }
861
998
 
999
+ void count::doCalc(const row_ptr& row, int index)
1000
+ {
1001
+ if (m_imple->targetKeys())
1002
+ groupFuncBase::doCalc(row, index);
1003
+ else
1004
+ m_imple->m_values[index] = m_imple->m_values[index] + 1;
1005
+ }
1006
+
862
1007
  groupFuncBase* count::clone()
863
1008
  {
864
1009
  count* p = new count();
@@ -874,26 +1019,35 @@ avg* avg::create(const fieldNames& targetNames, const _TCHAR* resultName)
874
1019
  return new avg(targetNames, resultName);
875
1020
  }
876
1021
 
1022
+ avg::avg() : groupFuncBase()
1023
+ {
1024
+ m_imple->setDecimals(4);
1025
+ }
1026
+
877
1027
  avg::avg(const fieldNames& targetNames, const _TCHAR* resultName)
878
- : sum(targetNames, resultName)
1028
+ : groupFuncBase(targetNames, resultName)
879
1029
  {
1030
+ m_imple->setDecimals(4);
880
1031
  }
881
1032
 
882
1033
  void avg::initResultVariable(int index)
883
1034
  {
884
- sum::initResultVariable(index);
1035
+ groupFuncBase::initResultVariable(index);
885
1036
  m_imple->m_counts.insert(m_imple->m_counts.begin() + index, 0);
886
1037
  }
887
1038
 
888
- void avg::doCalc(const row_ptr& row, int index)
1039
+ void avg::doCalcEachkey(const field& fd, int index)
889
1040
  {
890
- sum::doCalc(row, index);
1041
+ numeric_type tmp = 0;
1042
+ m_imple->m_values[index] += fieldValue(fd, tmp);
891
1043
  m_imple->m_counts[index] = m_imple->m_counts[index] + 1;
892
1044
  }
893
1045
 
894
1046
  avg::numeric_type avg::numericResult(int index) const
895
1047
  {
896
- return m_imple->m_values[index] / m_imple->m_counts[index];
1048
+ if (m_imple->m_counts[index])
1049
+ return m_imple->m_values[index] / m_imple->m_counts[index];
1050
+ return 0;
897
1051
  }
898
1052
 
899
1053
  groupFuncBase* avg::clone()
@@ -912,20 +1066,17 @@ min* min::create(const fieldNames& targetNames, const _TCHAR* resultName)
912
1066
  }
913
1067
 
914
1068
  min::min(const fieldNames& targetNames, const _TCHAR* resultName)
915
- : sum(targetNames, resultName), m_flag(true)
1069
+ : groupFuncBase(targetNames, resultName)
916
1070
  {
917
1071
  }
918
1072
 
919
- void min::doCalc(const row_ptr& row, int index)
1073
+ void min::doCalcEachkey(const field& fd, int index)
920
1074
  {
921
1075
  numeric_type tmp = 0;
922
- for (int i = 0; i < m_imple->targetKeys(); ++i)
923
- {
924
- tmp = fieldValue((*row)[m_imple->targetKey(i)], tmp);
925
- if (m_flag || m_imple->m_values[index] > tmp)
926
- m_flag = false;
1076
+ tmp = fieldValue(fd, tmp);
1077
+ if (insertFlag() || (tmp < m_imple->m_values[index]))
927
1078
  m_imple->m_values[index] = tmp;
928
- }
1079
+ clearInsertFlag();
929
1080
  }
930
1081
 
931
1082
  groupFuncBase* min::clone()
@@ -938,10 +1089,7 @@ groupFuncBase* min::clone()
938
1089
  min& min::operator=(const min& r)
939
1090
  {
940
1091
  if (this != &r)
941
- {
942
- m_flag = r.m_flag;
943
1092
  groupFuncBase::operator=(r);
944
- }
945
1093
  return *this;
946
1094
 
947
1095
  }
@@ -955,20 +1103,17 @@ max* max::create(const fieldNames& targetNames, const _TCHAR* resultName)
955
1103
  }
956
1104
 
957
1105
  max::max(const fieldNames& targetNames, const _TCHAR* resultName)
958
- : sum(targetNames, resultName), m_flag(true)
1106
+ : groupFuncBase(targetNames, resultName)
959
1107
  {
960
1108
  }
961
1109
 
962
- void max::doCalc(const row_ptr& row, int index)
1110
+ void max::doCalcEachkey(const field& fd, int index)
963
1111
  {
964
1112
  numeric_type tmp = 0;
965
- for (int i = 0; i < m_imple->targetKeys(); ++i)
966
- {
967
- tmp = fieldValue((*row)[m_imple->targetKey(i)], tmp);
968
- if (m_flag || m_imple->m_values[index] < tmp)
969
- m_flag = false;
1113
+ tmp = fieldValue(fd, tmp);
1114
+ if (insertFlag() || (tmp > m_imple->m_values[index]))
970
1115
  m_imple->m_values[index] = tmp;
971
- }
1116
+ clearInsertFlag();
972
1117
  }
973
1118
 
974
1119
  groupFuncBase* max::clone()
@@ -981,10 +1126,7 @@ groupFuncBase* max::clone()
981
1126
  max& max::operator=(const max& r)
982
1127
  {
983
1128
  if (this != &r)
984
- {
985
- m_flag = r.m_flag;
986
1129
  groupFuncBase::operator=(r);
987
- }
988
1130
  return *this;
989
1131
  }
990
1132
 
@@ -1014,23 +1156,31 @@ void last::doInit(const fielddefs* fdinfo)
1014
1156
  }
1015
1157
  }
1016
1158
 
1017
- void last::doCalc(const row_ptr& row, int index)
1159
+ void last::storeValue(const row_ptr& row, int index)
1018
1160
  {
1019
- if (m_imple->targetKeys())
1161
+ const field& fd = (*row)[m_imple->targetKey(0)];
1162
+ if (!fd.isNull())
1020
1163
  {
1021
1164
  numeric_type tmp = 0;
1022
1165
  if (m_imple->resultType() == ft_float)
1023
- m_imple->m_values[index] =
1024
- fieldValue((*row)[m_imple->targetKey(0)], tmp);
1166
+ m_imple->m_values[index] = fieldValue(fd, tmp);
1025
1167
  else
1026
1168
  {
1027
1169
  ushort_td len = m_imple->resultLen();
1028
1170
  unsigned char* p = m_imple->m_strings[index];
1029
- memcpy(p, (*row)[m_imple->targetKey(0)].ptr(), len);
1171
+ memcpy(p, fd.ptr(), len);
1030
1172
  }
1173
+ m_imple->m_nulls[index] = false;
1174
+ clearInsertFlag();
1031
1175
  }
1032
1176
  }
1033
1177
 
1178
+ void last::doCalc(const row_ptr& row, int index)
1179
+ {
1180
+ if (m_imple->targetKeys())
1181
+ storeValue(row, index);
1182
+ }
1183
+
1034
1184
  groupFuncBase* last::clone()
1035
1185
  {
1036
1186
  last* p = new last();
@@ -1047,30 +1197,15 @@ first* first::create(const fieldNames& targetNames, const _TCHAR* resultName)
1047
1197
  }
1048
1198
 
1049
1199
  first::first(const fieldNames& targetNames, const _TCHAR* resultName)
1050
- : last(targetNames, resultName),m_readed(false)
1200
+ : last(targetNames, resultName)
1051
1201
  {
1052
1202
 
1053
1203
  }
1054
1204
 
1055
1205
  void first::doCalc(const row_ptr& row, int index)
1056
1206
  {
1057
- if (m_readed == false)
1058
- {
1059
- if (m_imple->targetKeys())
1060
- {
1061
- numeric_type tmp = 0;
1062
- if (m_imple->resultType() == ft_float)
1063
- m_imple->m_values[index] =
1064
- fieldValue((*row)[m_imple->targetKey(0)], tmp);
1065
- else
1066
- {
1067
- ushort_td len = m_imple->resultLen();
1068
- unsigned char* p = m_imple->m_strings[index];
1069
- memcpy(p, (*row)[m_imple->targetKey(0)].ptr(), len);
1070
- }
1071
- }
1072
- m_readed = true;
1073
- }
1207
+ if (insertFlag() && m_imple->targetKeys())
1208
+ storeValue(row, index);
1074
1209
  }
1075
1210
 
1076
1211
  groupFuncBase* first::clone()
@@ -1082,17 +1217,13 @@ groupFuncBase* first::clone()
1082
1217
 
1083
1218
  void first::doReset()
1084
1219
  {
1085
- m_readed = false;
1086
1220
  groupFuncBase::reset();
1087
1221
  }
1088
1222
 
1089
1223
  first& first::operator=(const first& r)
1090
1224
  {
1091
1225
  if (this != &r)
1092
- {
1093
- m_readed = r.m_readed;
1094
1226
  last::operator=(r);
1095
- }
1096
1227
  return *this;
1097
1228
  }
1098
1229
 
@@ -1102,3 +1233,4 @@ first& first::operator=(const first& r)
1102
1233
  } // namespace protocol
1103
1234
  } // namespace db
1104
1235
  } // namespace bzs
1236
+