transactd 2.4.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+