Показать сообщение отдельно
Старый 20.08.2013, 16:10   #4  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Собственно, вот пара вспомогательных методов для класса 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).