00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "base/numeric.h"
00029 #include "smart/varobj.h"
00030 #include "base/vector.hpp"
00031 #include "base/list.hpp"
00032 #include "base/map.hpp"
00033 #include "base/memory.hpp"
00034 #include "base/common.hpp"
00035 #include "base/string.hpp"
00036 #include "base/stack.hpp"
00037 #include "smart/varmap.hpp"
00038 #include "smart/varvalue.hpp"
00039
00040 BEGIN_TERIMBER_NAMESPACE
00041 #pragma pack(4)
00042
00043 extern const char* response_dtd;
00045
00046 void
00047 var_container::intersect(const var_container& x)
00048 {
00049 sorted_container_data_t::const_iterator isrc = x._container.begin();
00050 sorted_container_data_t::iterator ithis = _container.begin();
00051
00052 while (isrc != x._container.end()
00053 && ithis != _container.end()
00054 )
00055 {
00056 if (isrc.key() < ithis.key())
00057 ++isrc;
00058 else if (ithis.key() < isrc.key())
00059 ithis = _container.erase(ithis);
00060 else
00061 {
00062 ++isrc;
00063 ++ithis;
00064 }
00065 }
00066
00067 while (ithis != _container.end())
00068 ithis = _container.erase(ithis);
00069 }
00070
00071
00072 void
00073 var_container::combine(const var_container& x)
00074 {
00075 sorted_container_data_t::const_iterator isrc = x._container.begin();
00076 sorted_container_data_t::iterator ithis = _container.begin();
00077
00078 while (isrc != x._container.end()
00079 && ithis != _container.end()
00080 )
00081 {
00082 if (isrc.key() < ithis.key())
00083 {
00084 ithis = _container.insert(_allocator, isrc.key(), *isrc).first;
00085 ++isrc;
00086 }
00087 else if (ithis.key() < isrc.key())
00088 ++ithis;
00089 else
00090 {
00091 ++isrc;
00092 ++ithis;
00093 }
00094 }
00095
00096 while (isrc != x._container.end())
00097 {
00098 _container.insert(_allocator, isrc.key(), *isrc);
00099 ++isrc;
00100 }
00101 }
00103
00104
00105 var_object_repository::var_object_repository(const var_object_schema& schema) :
00106 _schema(schema),
00107 _uint32_type_map(vt_ub4, false, false, _var_factory),
00108 _uint64_type_map(vt_ub8, false, false, _var_factory),
00109 _double_type_map(vt_double, false, false, _var_factory),
00110 _string_type_map(vt_string, false, false, _var_factory),
00111 _searchable_string_type_map(vt_string, true, false, _var_factory),
00112 _fuzzy_string_type_map(vt_string, false, true, _var_factory),
00113 _numeric_type_map(vt_numeric, false, false, _var_factory),
00114 _binary_type_map(vt_binary, false, false, _var_factory),
00115 _guid_type_map(vt_guid, false, false, _var_factory)
00116 {
00117 fuzzy_matcher_factory acc;
00118 _fuzzy_engine = acc.get_fuzzy_matcher(1024*1024*64);
00119 }
00120
00121 var_object_repository::~var_object_repository()
00122 {
00123 if (_fuzzy_engine)
00124 delete _fuzzy_engine;
00125 }
00126
00128 void
00129 var_object_repository::reset()
00130 {
00131 _key_generator.clear();
00132
00133 _objs_map.clear();
00134 _objs_all.reset();
00135
00136 _uint32_type_map.clear();
00137 _double_type_map.clear();
00138 _uint64_type_map.clear();
00139 _string_type_map.clear();
00140 _searchable_string_type_map.clear();
00141 _fuzzy_string_type_map.clear();
00142 _numeric_type_map.clear();
00143 _binary_type_map.clear();
00144 _guid_type_map.clear();
00145
00146 _iter_vec_all.reset();
00147
00148 _var_factory.reset();
00149 _fuzzy_engine->reset();
00150 }
00151
00153 size_t
00154 var_object_repository::count() const
00155 {
00156 return _objs_map.size();
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 bool
00213 var_object_repository::process_query(xml_designer* parser, var_container::sorted_container_allocator_t& all, byte_allocator& tmp, byte_allocator& inl)
00214 {
00215
00216 var_container where(all);
00217
00218 list_returns_index_t returns;
00219 var_object_values values;
00220
00221 parser->select_attribute_by_name("what");
00222 const char* what = parser->get_value();
00223 char w = what[0];
00224 parser->select_parent();
00225
00226 string_t err(0, &tmp);
00227
00228 switch (w)
00229 {
00230 case 'S':
00231
00232 if (parser->select_xpath("query/returns"))
00233 {
00234 if (!process_returns(parser, returns, tmp, inl, err))
00235 return process_error(parser, err);
00236
00237 parser->select_parent();
00238 }
00239
00240
00241 if (!parser->select_xpath("query/where"))
00242 return process_error(parser, "Can not find the required element \"where\"");
00243 else
00244 {
00245 if (!process_where(parser, where, tmp, inl, err))
00246 return process_error(parser, err);
00247
00248 parser->select_parent();
00249 }
00250 break;
00251 case 'I':
00252
00253 if (parser->select_xpath("query/returns"))
00254 {
00255 if (!process_returns(parser, returns, tmp, inl, err))
00256 return process_error(parser, err);
00257
00258 parser->select_parent();
00259 }
00260
00261
00262 if (!parser->select_xpath("query/values"))
00263 return process_error(parser, "Can not find the required element \"values\"");
00264 else
00265 {
00266 if (!process_values(parser, values, tmp, inl, err))
00267 return process_error(parser, err);
00268
00269 parser->select_parent();
00270 }
00271
00272 {
00273
00274 size_t pk = insert_object(values, tmp, inl, err);
00275
00276 if (!pk)
00277 return process_error(parser, err);
00278
00279 where._container.insert(where._allocator, pk, true);
00280 }
00281
00282 break;
00283 case 'U':
00284
00285 if (parser->select_xpath("query/returns"))
00286 {
00287 if (!process_returns(parser, returns, tmp, inl, err))
00288 return process_error(parser, err);
00289
00290 parser->select_parent();
00291 }
00292
00293
00294 if (!parser->select_xpath("query/values"))
00295 return process_error(parser, "Can not find the required element \"values\"");
00296 else
00297 {
00298 if (!process_values(parser, values, tmp, inl, err))
00299 return process_error(parser, err);
00300
00301 parser->select_parent();
00302 }
00303
00304
00305 if (!parser->select_xpath("query/where"))
00306 return process_error(parser, "Can not find the required element \"where\"");
00307 else
00308 {
00309 if (!process_where(parser, where, tmp, inl, err))
00310 return process_error(parser, err);
00311
00312 parser->select_parent();
00313 }
00314
00315 {
00316
00317 for (var_container::sorted_container_data_t::const_iterator it = where._container.begin(); it != where._container.end(); ++it)
00318 {
00319 size_t pk = it.key();
00320 if (!update_object(pk, values, tmp, inl, err))
00321 return process_error(parser, err);
00322 }
00323 }
00324 break;
00325 case 'D':
00326
00327 if (parser->select_xpath("query/returns"))
00328 {
00329 if (!process_returns(parser, returns, tmp, inl, err))
00330 return process_error(parser, err);
00331
00332 parser->select_parent();
00333 }
00334
00335
00336 if (!parser->select_xpath("query/where"))
00337 return process_error(parser, "Can not find the required element \"where\"");
00338 else
00339 {
00340 if (!process_where(parser, where, tmp, inl, err))
00341 return process_error(parser, err);
00342
00343 parser->select_parent();
00344 }
00345 break;
00346 default:
00347 assert(false);
00348 }
00349
00350 parser->load(0, 0, response_dtd, strlen(response_dtd));
00351 parser->add_child(ELEMENT_NODE, "response", 0, false);
00352 parser->add_child(ATTRIBUTE_NODE, "errCode", "0", true);
00353
00354
00355 for (var_container::sorted_container_data_t::const_iterator it = where._container.begin(); it != where._container.end(); ++it)
00356 {
00357 size_t pk = it.key();
00358
00359 parser->add_child(ELEMENT_NODE, "row", 0, false);
00360 char buf[32];
00361 str_template::strprint(buf, 32, "%d", pk);
00362 parser->add_child(ATTRIBUTE_NODE, "rowid", buf, true);
00363
00364 object_map_data_t::const_iterator ival = _objs_map.find(pk);
00365 assert(ival != _objs_map.end());
00366
00367 for (list_returns_index_t::const_iterator ic = returns.begin(); ic != returns.end(); ++ic)
00368 {
00369 parser->add_child(ELEMENT_NODE, "col", 0, false);
00370 parser->add_child(ATTRIBUTE_NODE, "name", _schema[*ic]._name, true);
00371
00372
00373 const char* value = 0;
00374
00375 try
00376 {
00377 if (_schema[*ic]._is_searchable)
00378 {
00379 value = (*ival)[*ic].key()._var_res._key._res;
00380 }
00381 else if (_schema[*ic]._is_fuzzy_match)
00382 {
00383 value = (*ival)[*ic].key()._var_res._ngram._res;
00384 }
00385 else
00386 {
00387 value = persist_value(_schema[*ic]._type, (*ival)[*ic].key()._var_res._val._value, &tmp);
00388 }
00389 }
00390 catch (exception& x)
00391 {
00392 return process_error(parser, x.what());
00393 }
00394
00395 parser->add_child(ATTRIBUTE_NODE, "val", value, true);
00396 parser->select_parent();
00397 }
00398
00399 parser->select_parent();
00400 }
00401
00402 switch (w)
00403 {
00404 case 'S':
00405 break;
00406 case 'I':
00407 break;
00408 case 'U':
00409 break;
00410 case 'D':
00411
00412 {
00413 for (var_container::sorted_container_data_t::const_iterator it = where._container.begin(); it != where._container.end(); ++it)
00414 {
00415 size_t pk = it.key();
00416 if (!delete_object(pk, tmp, err))
00417 return process_error(parser, err);
00418 }
00419 }
00420 break;
00421 default:
00422 assert(false);
00423 }
00424
00425 return true;
00426 }
00427
00428 bool
00429 var_object_repository::process_where(const xml_designer* parser,
00430 var_container& container,
00431 byte_allocator& tmp,
00432 byte_allocator& inl,
00433 string_t& err) const
00434 {
00435
00436 if (!parser->select_first_child())
00437 {
00438 err = "where cluase is empty";
00439 return false;
00440 }
00441
00442 do
00443 {
00444
00445 if (ELEMENT_NODE != parser->get_type())
00446 continue;
00447
00448 const char* name = parser->get_name();
00449
00450 switch (name[0])
00451 {
00452 case 'c':
00453 if (!process_condition(parser, container, false, tmp, inl, err))
00454 return false;
00455 break;
00456 case 'g':
00457 if (!process_group(parser, container, false, tmp, inl, err))
00458 return false;
00459 break;
00460 default:
00461 assert(false);
00462 }
00463 }
00464 while (parser->select_next_sibling());
00465
00466 parser->select_parent();
00467
00468 return true;
00469 }
00470
00471 bool
00472 var_object_repository::process_returns(const xml_designer* parser,
00473 list_returns_index_t& container,
00474 byte_allocator& tmp,
00475 byte_allocator& inl,
00476 string_t& err) const
00477 {
00478
00479 if (!parser->select_first_child())
00480 return true;
00481
00482 do
00483 {
00484
00485 if (ELEMENT_NODE != parser->get_type())
00486 continue;
00487
00488
00489 parser->select_attribute_by_name("name");
00490 const char* name = parser->get_value();
00491
00492 size_t index = 0;
00493 for (var_object_schema::const_iterator iter = _schema.begin(); iter != _schema.end(); ++iter, ++index)
00494 {
00495 if (!str_template::strnocasecmp(name, (const char*)_schema[index]._name, os_minus_one))
00496 break;
00497 }
00498
00499 if (index == _schema.size())
00500 {
00501 err = "Invalid column name: ";
00502 err += name;
00503 return false;
00504 }
00505
00506 container.push_back(tmp, index);
00507
00508 parser->select_parent();
00509 }
00510 while (parser->select_next_sibling());
00511
00512 parser->select_parent();
00513
00514 return true;
00515 }
00516
00517 bool
00518 var_object_repository::process_values(const xml_designer* parser,
00519 var_object_values& container,
00520 byte_allocator& tmp,
00521 byte_allocator& inl,
00522 string_t& err) const
00523 {
00524
00525 container.resize(tmp, _schema.size());
00526
00527
00528 if (!parser->select_first_child())
00529 return true;
00530
00531 do
00532 {
00533
00534 if (ELEMENT_NODE != parser->get_type())
00535 continue;
00536
00537
00538 parser->select_attribute_by_name("name");
00539 const char* name = parser->get_value();
00540
00541 size_t index = 0;
00542 for (var_object_schema::const_iterator iter = _schema.begin(); iter != _schema.end(); ++iter, ++index)
00543 {
00544 if (!str_template::strnocasecmp(name, (const char*)_schema[index]._name, os_minus_one))
00545 break;
00546 }
00547
00548 if (index == _schema.size())
00549 {
00550 err = "Invalid column name: ";
00551 err += name;
00552 return false;
00553 }
00554
00555 parser->select_parent();
00556
00557 const char* value = 0;
00558 if (parser->select_attribute_by_name("val"))
00559 {
00560 value = parser->get_value();
00561
00562 container[index]._not_null = true;
00563
00564 try
00565 {
00566 container[index]._value = parse_value(_schema[index]._type, value, os_minus_one, &tmp);
00567 }
00568 catch (exception& x)
00569 {
00570 err = x.what();
00571 return false;
00572 }
00573
00574 parser->select_parent();
00575 }
00576
00577 container[index]._specified = true;
00578 }
00579 while (parser->select_next_sibling());
00580
00581 parser->select_parent();
00582
00583 return true;
00584 }
00585
00586 bool
00587 var_object_repository::process_condition(const xml_designer* parser,
00588 var_container& container,
00589 bool intersect,
00590 byte_allocator& tmp,
00591 byte_allocator& inl,
00592 string_t& err) const
00593 {
00594
00595
00596
00597
00598 parser->select_attribute_by_name("how");
00599 char how[2];
00600 memcpy(how, parser->get_value(), 2);
00601 parser->select_parent();
00602
00603 bool deep = false;
00604 if (parser->select_attribute_by_name("deep"))
00605 {
00606 deep = !strcmp(parser->get_value(), "1") || !strcmp(parser->get_value(), "true");
00607 parser->select_parent();
00608 }
00609
00610 ngram_quality nq = nq_high;
00611 if (parser->select_attribute_by_name("nq"))
00612 {
00613 if (!strcmp(parser->get_value(), "low"))
00614 nq = nq_low;
00615 else if (!strcmp(parser->get_value(), "normal"))
00616 nq = nq_normal;
00617
00618 parser->select_parent();
00619 }
00620
00621 phonetic_quality pq = pq_high;
00622 if (parser->select_attribute_by_name("pq"))
00623 {
00624 if (!strcmp(parser->get_value(), "low"))
00625 pq = pq_low;
00626 else if (!strcmp(parser->get_value(), "normal"))
00627 pq = pq_normal;
00628
00629 parser->select_parent();
00630 }
00631
00632 size_t index = 0;
00633 string_t name(0, &inl);
00634 if (parser->select_attribute_by_name("name"))
00635 {
00636 name = parser->get_value();
00637 parser->select_parent();
00638
00639
00640 for (var_object_schema::const_iterator iter = _schema.begin(); iter != _schema.end(); ++iter, ++index)
00641 {
00642 if (name == iter->_name)
00643 break;
00644 }
00645
00646
00647 if (index == _schema.size())
00648 {
00649 err = "Invalid column name: ";
00650 err += name;
00651 return false;
00652 }
00653 }
00654
00655 bool by_rowid = name.length() == 0;
00656 vt_types type = by_rowid ? vt_ub4 : _schema[index]._type;
00657 bool searchable = by_rowid ? false : _schema[index]._is_searchable;
00658 bool fuzzymatch = by_rowid ? false : _schema[index]._is_fuzzy_match;
00659
00660
00661 parser->select_attribute_by_name("val");
00662 const char* value = parser->get_value();
00663
00664 var_value val;
00665 val._not_null = (value != 0);
00666
00667 try
00668 {
00669 val._value = parse_value(type, value, os_minus_one, &tmp);
00670 }
00671 catch (exception& x)
00672 {
00673 err = x.what();
00674 return false;
00675 }
00676
00677 parser->select_parent();
00678
00679 var_value castval;
00680 vt_types casttype = cast_to_common_type(type, val, castval, tmp);
00681
00682 if (by_rowid)
00683 {
00684 if (_objs_map.find(castval._value.ulVal) != _objs_map.end())
00685 container._container.insert(container._allocator, castval._value.ulVal, true);
00686 }
00687 else
00688 {
00689 const var_object_map_t* pv = get_v_object_pointer(casttype, searchable);
00690 if (!pv)
00691 {
00692 err = "Not enough memory";
00693 return false;
00694 }
00695
00696 main_map_key key(casttype, castval, 0);
00697 pk_column min_filter(0, index);
00698 pk_column max_filter(~0, index);
00699
00700 switch (how[0])
00701 {
00702 case 'G':
00703 {
00704 switch (how[1])
00705 {
00706 case 'T':
00707 intersect ?
00708 pv->intersect_greater_resource(key, container, min_filter, max_filter, false) :
00709 pv->find_greater_resource(key, container, min_filter, max_filter, false);
00710 break;
00711 case 'E':
00712 intersect ?
00713 pv->intersect_greater_resource(key, container, min_filter, max_filter, true) :
00714 pv->find_greater_resource(key, container, min_filter, max_filter, true);
00715 break;
00716 default:
00717 assert(false);
00718 }
00719 }
00720 break;
00721 case 'L':
00722 {
00723 switch (how[1])
00724 {
00725 case 'T':
00726 intersect ?
00727 pv->intersect_less_resource(key, container, min_filter, max_filter, false) :
00728 pv->find_less_resource(key, container, min_filter, max_filter, false);
00729 break;
00730 case 'E':
00731 intersect ?
00732 pv->intersect_less_resource(key, container, min_filter, max_filter, true) :
00733 pv->find_less_resource(key, container, min_filter, max_filter, true);
00734 break;
00735 default:
00736 assert(false);
00737 }
00738 }
00739 break;
00740 case 'E':
00741 intersect ?
00742 pv->intersect_exact_resource(key, container, min_filter, max_filter) :
00743 pv->find_exact_resource(key, container, min_filter, max_filter);
00744 break;
00745 case 'N':
00746 intersect ?
00747 pv->intersect_exact_resource(key, container, min_filter, max_filter) :
00748 pv->find_exact_resource(key, container, min_filter, max_filter);
00749 break;
00750 case 'P':
00751 if (casttype != vt_string)
00752 return false;
00753
00754
00755
00756
00757 if (searchable)
00758 {
00759 main_map_key pkey(castval._value.strVal, 0);
00760 intersect ?
00761 pv->intersect_partial_resource(pkey, deep, container, min_filter, max_filter) :
00762 pv->find_partial_resource(pkey, deep, container, min_filter, max_filter);
00763 }
00764 break;
00765 case 'F':
00766 if (casttype != vt_string)
00767 return false;
00768
00769 if (fuzzymatch)
00770 {
00771
00772 _list< size_t > fuzzy_container;
00773 _fuzzy_engine->match(nq, pq, castval._value.strVal, tmp, inl, fuzzy_container);
00774
00775 intersect ?
00776 pv->intersect_fuzzy_resource(fuzzy_container, container, min_filter, max_filter) :
00777 pv->find_fuzzy_resource(fuzzy_container, container, min_filter, max_filter);
00778 }
00779
00780 break;
00781 default:
00782 assert(false);
00783 return false;
00784 }
00785 }
00786 return true;
00787 }
00788
00789 bool
00790 var_object_repository::process_group(const xml_designer* parser,
00791 var_container& container,
00792 bool intersect,
00793 byte_allocator& tmp,
00794 byte_allocator& inl,
00795 string_t& err) const
00796 {
00797 parser->select_attribute_by_name("join");
00798 char join = *parser->get_value();
00799 parser->select_parent();
00800
00801
00802 var_container groupcontainer(container._allocator);
00803 bool group_intersect = false;
00804
00805
00806 if (parser->select_first_child())
00807 {
00808 do
00809 {
00810
00811 if (ELEMENT_NODE != parser->get_type())
00812 continue;
00813
00814 const char* name = parser->get_name();
00815
00816 switch (name[0])
00817 {
00818 case 'c':
00819 if (!process_condition(parser, groupcontainer, group_intersect && join == 'A', tmp, inl, err))
00820 return false;
00821 break;
00822 case 'g':
00823 if (!process_group(parser, groupcontainer, group_intersect && join == 'A', tmp, inl, err))
00824 return false;
00825 break;
00826 default:
00827 assert(false);
00828 }
00829
00830 group_intersect = true;
00831 }
00832 while (parser->select_next_sibling());
00833 parser->select_parent();
00834 }
00835
00836 intersect ? container.intersect(groupcontainer) : container.combine(groupcontainer);
00837
00838 return true;
00839 }
00840
00841
00842 size_t
00843 var_object_repository::insert_object(const var_object_values& values, byte_allocator& tmp, byte_allocator& inl, string_t& err)
00844 {
00845
00846 if (_schema.size() != values.size())
00847 {
00848 assert(false);
00849 err = "Number of values does not match number of columns";
00850 return 0;
00851 }
00852
00853 iter_vector_t iters;
00854 iters.resize(_iter_vec_all, _schema.size());
00855
00856
00857 size_t pk = _key_generator.generate();
00858
00859
00860 size_t index = 0;
00861 for (var_object_schema::const_iterator iter = _schema.begin(); iter != _schema.end(); ++iter, ++index)
00862 {
00863
00864 var_value val;
00865 vt_types mtype = cast_to_common_type(iter->_type, values[index], val, tmp);
00866 var_object_map_t* pv = get_v_object_pointer(mtype, iter->_is_searchable);
00867 if (!pv)
00868 {
00869 err = "Not enough memory";
00870 return 0;
00871 }
00872
00873 pk_column dkey(pk, index);
00874
00875 if (iter->_is_searchable)
00876 {
00877 main_map_key key(val._value.strVal, 0);
00878 iters[index] = pv->add_resource(key, dkey);
00879 }
00880 else if (iter->_is_fuzzy_match)
00881 {
00882 size_t ident = _fuzzy_engine->add(val._value.strVal, tmp);
00883 main_map_key key(ident, val._value.strVal, 0);
00884 iters[index] = pv->add_resource(key, dkey);
00885 }
00886 else
00887 {
00888 main_map_key key(mtype, val, 0);
00889 iters[index] = pv->add_resource(key, dkey);
00890 }
00891 }
00892
00893
00894 _objs_map.insert(_objs_all, pk, iters);
00895 return pk;
00896 }
00897
00898
00899 bool
00900 var_object_repository::delete_object(size_t pk, byte_allocator& tmp, string_t& err)
00901 {
00902
00903 object_map_data_t::iterator iter_object = _objs_map.find(pk);
00904 if (iter_object == _objs_map.end())
00905 {
00906 err = "Object not found";
00907 return false;
00908 }
00909
00910
00911 size_t index = 0;
00912 for (var_object_schema::const_iterator iter = _schema.begin(); iter != _schema.end(); ++iter, ++index)
00913 {
00914
00915 vt_types mtype = map_type(iter->_type);
00916 var_object_map_t* pv = get_v_object_pointer(mtype, iter->_is_searchable);
00917 if (!pv)
00918 {
00919 err = "Not enough memory";
00920 return false;
00921 }
00922
00923 if (iter->_is_fuzzy_match)
00924 {
00925 _fuzzy_engine->remove((*iter_object)[index].key()._var_res._ngram._fuzzy_key, tmp);
00926 }
00927
00928 pk_column dkey(pk, index);
00929 if (!pv->remove_resource((*iter_object)[index], dkey))
00930 {
00931 err = "Object not found";
00932 return false;
00933 }
00934 }
00935
00936
00937 iter_object->clear(_iter_vec_all);
00938 _objs_map.erase(iter_object);
00939
00940 _key_generator.save(pk);
00941 return true;
00942 }
00943
00944
00945 bool
00946 var_object_repository::update_object(size_t pk, const var_object_values& values, byte_allocator& tmp, byte_allocator& inl, string_t& err)
00947 {
00948
00949 if (_schema.size() != values.size())
00950 {
00951 assert(false);
00952 err = "Number of values does not match number of columns";
00953 return 0;
00954 }
00955
00956
00957 object_map_data_t::iterator iter_object = _objs_map.find(pk);
00958 if (iter_object == _objs_map.end())
00959 {
00960 err = "Object not found";
00961 return false;
00962 }
00963
00964
00965 size_t index = 0;
00966 for (var_object_schema::const_iterator iter = _schema.begin(); iter != _schema.end(); ++iter, ++index)
00967 {
00968 if (!values[index]._specified)
00969 continue;
00970
00971
00972 var_value val;
00973 vt_types mtype = cast_to_common_type(iter->_type, values[index], val, tmp);
00974
00975 var_object_map_t* pv = get_v_object_pointer(mtype, iter->_is_searchable);
00976 if (!pv)
00977 {
00978 err = "Not enough memory";
00979 return false;
00980 }
00981
00982 if (iter->_is_fuzzy_match)
00983 {
00984 _fuzzy_engine->remove((*iter_object)[index].key()._var_res._ngram._fuzzy_key, tmp);
00985 }
00986
00987 pk_column dkey(pk, index);
00988 if (!pv->remove_resource((*iter_object)[index], dkey))
00989 {
00990 err = "Object not found";
00991 return false;
00992 }
00993
00994
00995 if (iter->_is_searchable)
00996 {
00997
00998 main_map_key key(val._value.strVal, 0);
00999 (*iter_object)[index] = pv->add_resource(key, dkey);
01000 }
01001 else if (iter->_is_fuzzy_match)
01002 {
01003 size_t ident = _fuzzy_engine->add(val._value.strVal, tmp);
01004 main_map_key key(ident, val._value.strVal, 0);
01005 (*iter_object)[index] = pv->add_resource(key, dkey);
01006 }
01007 else
01008 {
01009
01010 main_map_key key(mtype, val, 0);
01011 (*iter_object)[index] = pv->add_resource(key, dkey);
01012 }
01013 }
01014
01015 return true;
01016 }
01017
01018 vt_types
01019 var_object_repository::cast_to_common_type(vt_types type,
01020 const var_value& in,
01021 var_value& out,
01022 byte_allocator& tmp) const
01023 {
01024 out._not_null = in._not_null;
01025
01026 switch (type)
01027 {
01028 case vt_enum:
01029 case vt_unknown:
01030 case vt_empty:
01031 case vt_null:
01032 assert(false);
01033 return vt_unknown;
01034 case vt_bool:
01035 out._value.ulVal = in._not_null ? (in._value.boolVal ? 1 : 0) : 0;
01036 return vt_ub4;
01037 case vt_sb1:
01038 out._value.ulVal = in._not_null ? (ub4_t)in._value.cVal : 0;
01039 return vt_ub4;
01040 case vt_ub1:
01041 out._value.ulVal = in._not_null ? (ub4_t)in._value.bVal : 0;
01042 return vt_ub4;
01043 case vt_sb2:
01044 out._value.ulVal = in._not_null ? (ub4_t)in._value.iVal : 0;
01045 return vt_ub4;
01046 case vt_ub2:
01047 out._value.ulVal = in._not_null ? (ub4_t)in._value.uiVal : 0;
01048 return vt_ub4;
01049 case vt_sb4:
01050 out._value.ulVal = in._not_null ? (ub4_t)in._value.lVal : 0;
01051 return vt_ub4;
01052 case vt_ub4:
01053 out._value.ulVal = in._not_null ? in._value.ulVal : 0;
01054 return vt_ub4;
01055 case vt_float:
01056 #ifdef OS_64BIT
01057 out._value.dblVal = (double)in._value.fltVal;
01058 #else
01059 {
01060 double* p = (double*)tmp.allocate(sizeof(double));
01061 if (!p)
01062 {
01063 assert(false);
01064 return vt_unknown;
01065 }
01066
01067 *p = (double)in._value.fltVal;
01068 out._value.dblVal = p;
01069 }
01070 #endif
01071 return vt_double;
01072 case vt_double:
01073 out._value.dblVal = in._value.dblVal;
01074 return vt_double;
01075 case vt_sb8:
01076 case vt_date:
01077 #ifdef OS_64BIT
01078 out._value.uintVal = (ub8_t)in._value.intVal;
01079 #else
01080 if (in._value.intVal)
01081 {
01082 ub8_t* p = (ub8_t*)tmp.allocate(sizeof(ub8_t));
01083 if (!p)
01084 {
01085 assert(false);
01086 return vt_unknown;
01087 }
01088
01089 *p = (ub8_t)*in._value.intVal;
01090 out._value.uintVal = p;
01091 }
01092 else
01093 out._value.uintVal = 0;
01094 #endif
01095 return vt_ub8;
01096 case vt_ub8:
01097 out._value.uintVal = in._value.uintVal;
01098 return vt_ub8;
01099 case vt_string:
01100 out._value.strVal = in._value.strVal;
01101 return vt_string;
01102 case vt_wstring:
01103 out._value.strVal = str_template::unicode_to_multibyte(tmp, out._value.wstrVal, os_minus_one);
01104 return vt_string;
01105 case vt_decimal:
01106 case vt_numeric:
01107 out._value.bufVal = in._value.bufVal;
01108 return vt_numeric;
01109 case vt_binary:
01110 out._value.bufVal = in._value.bufVal;
01111 return vt_binary;
01112 case vt_guid:
01113 out._value.guidVal = in._value.guidVal;
01114 return vt_guid;
01115 }
01116
01117 assert(false);
01118 return vt_unknown;
01119 }
01120
01121 vt_types
01122 var_object_repository::map_type(vt_types type) const
01123 {
01124 switch (type)
01125 {
01126 case vt_enum:
01127 case vt_unknown:
01128 case vt_empty:
01129 case vt_null:
01130 assert(false);
01131 return vt_unknown;
01132 case vt_bool:
01133 case vt_sb1:
01134 case vt_ub1:
01135 case vt_sb2:
01136 case vt_ub2:
01137 case vt_sb4:
01138 case vt_ub4:
01139 return vt_ub4;
01140 case vt_float:
01141 case vt_double:
01142 return vt_double;
01143 case vt_sb8:
01144 case vt_date:
01145 case vt_ub8:
01146 return vt_ub8;
01147 case vt_string:
01148 return vt_string;
01149 case vt_wstring:
01150 return vt_string;
01151 case vt_decimal:
01152 case vt_numeric:
01153 return vt_numeric;
01154 case vt_binary:
01155 return vt_binary;
01156 case vt_guid:
01157 return vt_guid;
01158 }
01159
01160 assert(false);
01161 return vt_unknown;
01162 }
01163
01164 var_object_map_t*
01165 var_object_repository::get_v_object_pointer(vt_types type, bool searchable)
01166 {
01167 switch (type)
01168 {
01169 case vt_ub4:
01170 return &_uint32_type_map;
01171 case vt_double:
01172 return &_double_type_map;
01173 case vt_ub8:
01174 return &_uint64_type_map;
01175 case vt_string:
01176 return searchable ? &_searchable_string_type_map : &_string_type_map;
01177 case vt_numeric:
01178 return &_numeric_type_map;
01179 case vt_binary:
01180 return &_binary_type_map;
01181 case vt_guid:
01182 return &_guid_type_map;
01183 case vt_unknown:
01184 default:
01185 assert(false);
01186 return 0;
01187 }
01188 }
01189
01190 const var_object_map_t*
01191 var_object_repository::get_v_object_pointer(vt_types type, bool searchable) const
01192 {
01193 switch (type)
01194 {
01195 case vt_ub4:
01196 return &_uint32_type_map;
01197 case vt_double:
01198 return &_double_type_map;
01199 case vt_ub8:
01200 return &_uint64_type_map;
01201 case vt_string:
01202 return searchable ? &_searchable_string_type_map : &_string_type_map;
01203 case vt_numeric:
01204 return &_numeric_type_map;
01205 case vt_binary:
01206 return &_binary_type_map;
01207 case vt_guid:
01208 return &_guid_type_map;
01209 case vt_unknown:
01210 default:
01211 assert(false);
01212 return 0;
01213 }
01214 }
01215
01216 bool
01217 var_object_repository::process_error(xml_designer* parser, const char* err) const
01218 {
01219 parser->load(0, 0, response_dtd, strlen(response_dtd));
01220 parser->add_child(ELEMENT_NODE, "result", 0, false);
01221 parser->add_child(ATTRIBUTE_NODE, "errCode", "-1", true);
01222 parser->add_child(ATTRIBUTE_NODE, "errDesc", err, true);
01223 return false;
01224 }
01225
01227
01229 bool
01230 var_object_repository::select_object(size_t pk,
01231 var_object_values& row,
01232 byte_allocator& tmp
01233 ) const
01234 {
01235
01236 object_map_data_t::const_iterator ival = _objs_map.find(pk);
01237 if (ival == _objs_map.end())
01238 return false;
01239
01240 size_t cols = ival->size();
01241
01242 if (!row.resize(tmp, cols))
01243 return false;
01244
01245 for (size_t c = 0; c < cols; ++c)
01246 {
01247 if (_schema[c]._is_searchable)
01248 {
01249 row[c]._value.strVal = (*ival)[c].key()._var_res._key._res;
01250 row[c]._not_null = true;
01251 row[c]._specified = true;
01252 }
01253 else if (_schema[c]._is_fuzzy_match)
01254 {
01255 row[c]._value.strVal = (*ival)[c].key()._var_res._ngram._res;
01256 row[c]._not_null = true;
01257 row[c]._specified = true;
01258 }
01259 else
01260 {
01261 row[c] = (*ival)[c].key()._var_res._val;
01262 row[c]._specified = true;
01263 }
01264 }
01265
01266 return true;
01267 }
01268
01271 bool
01272 var_object_repository::select_object(const var_object_values& key,
01273 var_object_values& row,
01274 byte_allocator& tmp,
01275 var_container::sorted_container_allocator_t& conall,
01276 size_t& pk
01277 ) const
01278 {
01279
01280 var_container container(conall);
01281
01282
01283 if (!find_by_row(key, container, tmp))
01284 return false;
01285
01286 if (container._container.size() != 1)
01287 return false;
01288
01289 pk = container._container.begin().key();
01290
01291 return select_object(pk, row, tmp);
01292 }
01293
01296 bool
01297 var_object_repository::delete_object(const var_object_values& key,
01298 byte_allocator& tmp,
01299 byte_allocator& inl,
01300 string_t& err
01301 )
01302 {
01303
01304 var_container container(tmp);
01305
01306 if (!find_by_row(key, container, tmp))
01307 return false;
01308
01309
01310 for (var_container::sorted_container_data_t::const_iterator it = container._container.begin(); it != container._container.end(); ++it)
01311 {
01312 inl.reset();
01313 if (!delete_object(it.key(), inl, err))
01314 return false;
01315 }
01316
01317 return true;
01318 }
01319
01321 bool
01322 var_object_repository::find_by_conditions( const xml_designer* parser,
01323 var_container& container,
01324 byte_allocator& tmp,
01325 byte_allocator& inl,
01326 string_t& err
01327 ) const
01328 {
01329 return process_where(parser, container, tmp, inl, err);
01330 }
01331
01333 bool
01334 var_object_repository::find_by_condition( const xml_designer* parser,
01335 var_container& container,
01336 byte_allocator& tmp,
01337 byte_allocator& inl,
01338 string_t& err
01339 ) const
01340 {
01341 return process_condition(parser, container, false, tmp, inl, err);
01342 }
01344 bool
01345 var_object_repository::find_by_row( const var_object_values& values,
01346 var_container& container,
01347 byte_allocator& tmp
01348 ) const
01349 {
01350
01351 if (values.size() != _schema.size())
01352 return false;
01353
01354
01355 size_t index = 0;
01356 bool intersect = false;
01357
01358 for (var_object_values::const_iterator iter = values.begin(); iter != values.end(); ++iter, ++index)
01359 {
01360 if (!iter->_specified)
01361 continue;
01362
01363
01364 var_value castval;
01365 vt_types casttype = cast_to_common_type(_schema[index]._type, values[index], castval, tmp);
01366
01367 const var_object_map_t* pv = get_v_object_pointer(casttype, _schema[index]._is_searchable);
01368 if (!pv)
01369 return false;
01370
01371 main_map_key key(casttype, castval, 0);
01372 pk_column min_filter(0, index);
01373 pk_column max_filter(~0, index);
01374
01375
01376 intersect ?
01377 pv->intersect_exact_resource(key, container, min_filter, max_filter) :
01378 pv->find_exact_resource(key, container, min_filter, max_filter);
01379
01380 intersect = true;
01381 }
01382
01383 return true;
01384 }
01385
01386 #pragma pack()
01387 END_TERIMBER_NAMESPACE