19.08.2013, 19:00 | #1 |
Участник
|
new Query(q1); и Query(q1.pack()); - есть ли разница ?
Есть запрос q1.
Есть ли разница, каким образом создавать его копию: через q2 = new Query(q1.pack()); или через q3 = new Query(q1); ? AX2009, RU2 |
|
19.08.2013, 21:16 | #2 |
Участник
|
Из известных мне особенностей упаковки Query: теряются dynalink'и (для этого надо явно отключить проверку через параметр _doCheck, иначе Query с dynalink'ами не упакуется и выкинет исключение) и теряются хинты forceNestedLoop, forceSelectOrder. Иногда потеря этих хинтов ведет к серьезным проблемам с производительностью, впрочем, их и не используют "просто так". А еще важно, на каком уровне (клиенте или сервере) создан исходный Query и на каком будет использоваться результирующий: при передаче с уровня на уровень лучше сделать копию исходного Query, используя переупаковку.
|
|
|
За это сообщение автора поблагодарили: mazzy (10), MikeR (15), IKA (1), dech (2). |
20.08.2013, 12:29 | #3 |
Участник
|
здорово, спасибо!
|
|
20.08.2013, 16:10 | #4 |
Участник
|
Собственно, вот пара вспомогательных методов для класса SysQuery. С помощью первого можно безопасно копировать запросы, в т.ч. при передаче с клиента на сервер и обратно.
X++: /// <summary> /// копируем запрос, по ходу перебивая dynalink'и в locked ranges /// </summary> /// <param name="_q"> /// исходный запрос /// </param> /// <param name="_copyHints"> /// надо ли копировать хинты forceSelectOrder и forceNestedLoops /// </param> /// <returns> /// копия исходного запроса /// </returns> /// <remarks> /// может быть полезно, если запрос затем будет сохраняться в SysLastValue, либо передавать между клиентом и сервером, либо рихтовать под ные нужды (подсчет записей) /// </remarks> /// <exception cref="Exception::Error"> /// выбрасывается, если исходный запрос - "вырожденный" либо вовсе null /// </exception> public client server static Query copyQuery( Query _q, boolean _copyHints = true ) { QueryBuildDataSource qbdsOld; QueryBuildDataSource qbdsNew; QueryBuildDynalink qbdl; Query ret; str sq; Counter n; ; if (!(_q && _q.dataSourceCount() > 0)) { throw error(Error::wrongUseOfFunction(funcname())); } ret = new Query(_q.pack(false)); // создать копию запроса if (_copyHints) { // на эти извращения пришлось пойти потому, что у методов Query forceSelectOrder() и forceNestedLoop() параметры обязательны, // поэтому их нельзя использовать как нормальные свойства для определения наличия или отсутствия соотв. хинтов в запросе sq = _q.dataSourceNo(1).toString(); if (match(@"^SELECT WITH.* SELECT_ORDER[ ,]", sq)) { ret.forceSelectOrder(true); } if (match(@"^SELECT WITH.* NESTED_LOOP[ ,]", sq)) { ret.forceNestedLoop(true); } } qbdsNew = ret.dataSourceNo(1); // из нового запроса qbdsOld = _q.dataSourceNo(1); // из исходного запроса for (n = 1; n <= qbdsOld.dynalinkCount(); n++) { qbdl = qbdsOld.dynalink(n); // очищаем *все* range'и по данному полю и ставим свой range с нужным статусом SysQuery::setFieldRange(qbdsNew, qbdl.field(), queryValue(qbdl.cursor().(qbdl.dynamicField())), RangeStatus::Locked); } return ret; } /// <summary> /// устанавливает фильтр по полю, удаляя все прочие и опционально управляя его статусом /// </summary> public static QueryBuildRange setFieldRange( QueryBuildDataSource _qbds, fieldId _fieldId, Range _rangeValue, RangeStatus _rangeStatus = RangeStatus::Open ) { QueryBuildRange ret; ; if (_qbds) { while (_qbds.findRange(_fieldId)) { _qbds.clearRange(_fieldId); } ret = _qbds.addRange(_fieldId); ret.value(_rangeValue); ret.status(_rangeStatus); } return ret; } |
|
|
За это сообщение автора поблагодарили: raz (10), virtuoso (1). |