Итак, несколько основных моментов при использовании фильтра:

  • сам по себе VIEW не отличается большим интеллектом.
  • если не задан явно PROP:ORDER и не указан перед открытием VIEW используемый ключ, то при построении выборки игнорируются все ключи и выборка строится по порядку записей. Естественно — очень медленно, т.к. необходимо перебирать ВСЕ записи. В этом случае, перед открытием VIEW можно и не ставить операторы SET(View) или SET(File), но НЕОБХОДИМО ставить один из них  перед первым NEXT()/PREVIOUS()! Иначе, сами понимаете, не будет инициализирован порядок просмотра выборки.
  • если не задан явно PROP:ORDER, но перед открытием VIEW задан ключ просмотра, то именно этот ключ и будет использован при построении выборки. Если ключ не подходит для заданного фильтра, то скорость выборки маленькая. Если задан правильный ключ, то первая и последняя записи выборки будут считаны мгновенно. Скорость самой выборки всего диапазона будет зависеть от ее размера. Но, в любом случае, это будет самый оптимальный вариант. Так что, как видим, VIEW не блещет интеллектом и не выбирает сам подходящий ключ — все делает программист.
  • если задан явно PROP:ORDER, то теперь все зависит от того, совпадает ли он с ключом, оптимальным для фильтра. Дело в том, что независимо от того, какой ключ будет задан перед открытием VIEW, выбирается ВСЕГДА самый оптимальный для заданной сортировки. Вот здесь и проявляется интеллектуальность VIEW. Если выбранный ключ является оптимальным и для заданного фильтра, то такая выборка будет самой оптимальной. В противном случае я даже затрудняюсь сказать, какой ключ используется или используется выборка по порядку записей. По крайней мере, автоматом НЕ ВЫБИРАЕТСЯ первый ключ — это точно. В результате проведенных тестов есть подозрение, что в некоторых случаях (разные фильтры) выбирается оптимальный ключ, т.к. в этих случаях время построения выборки с сортировкой меньше времени полного прохода всех записей.

Подводя итог под вышесказанным, можно рекомендовать следующие Читать далее

Поменял в базе ID записи с Long на String(20)

Фильтры и итоги в бровзе раза в 4 замедлились 🙁
Отвечаю сразу по двум письмам на данную тему (второе от Владимира Смелика).
Замедление — закономерный результат.
И дело даже не в том, что изменился размер самого поля. Все дело — в принципиально разной обработке полей типа LONG и STRING. Если для обработки полей типа LONG компилятор генерит обычный машинный код с простыми ASM-операторами, то даже для простейших операций с переменными типа STRING используется специальный внутренний стек. Например, для выполнения оператора Clip(STR) генерится (упрощенно) следующий код:

  • «затолкнуть» (Push) переменную STR в стек 2 ASM-команды + вызов стековой функции
  • выполнить операцию CLIP() над содержимым вершины стека один вызов стековой функции
  • «вытолкнуть» (Pop) результат из стека в переменную STR 2 ASM-команды + вызов стековой функции А для операции сравнения двух операндов, одним из которых является строка, генерится (без применения CLIP() или UPPER()):
  • PushToStack(STR)
  • PushToStack(STR1)
  • CompareStack()

А если, не дай бог, вторым операндом будет не строка, а, например Читать далее

Как правильно задать имя переменной, находящейся в куче вложенных структур?

Как правильно задать имя переменной, находящейся в куче вложенных структур? Вот простой пример.

g1      group  ! в оригинале - record файла
l       long
         end
q       queue,type
g1      like(g1)
         end

Так работает:

g2      group
q2      &q
         end
     CODE
  g2.q2.g1.l = 1

А так — нет, хотя скобки массива вроде правильно стоят:

g2      group,dim(2)
q2      &q
         end
     CODE
  g2[1].q2.g1.l = 1  ! ERROR: field not found: g1

Что не так? Вообще-то Кларин компилятор очень не любит массивы рефералов!

А у тебя как раз получается такой массив. Так что, возможно, именно из-за этого он и ругается. А если тебе надо сделать что-то типа массива очередей, то самый простой вариант — делать не через массив а через очередь.
Т.е.:

FilesQue  QUEUE
RecsQue     &Q
          END

Если нужен массив на два элемента — делай две записи. И т.д. Такой вариант будет работать и компилятор спокойно его пропустит.

Возвращаюсь у своему вопросу: необходимо подключиться к серверу Velocis программой на Кларионе.

Сразу скажу, что с данным сервером не работал, поэтому мои рекомендации можешь рассматривать просто как мысли вслух программиста с большим стажем работы с БД.

Правильно ли я выбрал формат Dbf. Может, кто предложит что лучше?  Опять-же — для чего «сливаются» данные? Если для дальнейшей работы с ними

прямо в этих базах, то — сойдет. Если же предполагается простая закачка данных из этих баз уже в рабочую базу, то в качестве альтернативы я бы предложил рассмотреть простой ASCII-файл. Чтение из него не медленнее чем из DBF, а то и быстрее. Зато точно не будет никаких сюрпризов, как это бывает при работе с DBF из Клариона. Читать далее

Недавно в буржуинской переписке видал, что операции с ULONG медленнее чем с LONG в 100-200 раз.

Недавно в буржуинской переписке промелькнуло, что операции с ULONG медленнее чем с LONG в 100-200 раз. И предполагается что это потому что базовый тип для ULONG есть DECIMAL. И вот вопросик (вероятно к Олегу 🙂 ) Что вы думаете по этому поводу? Действительно ли Decimal  базовый тип для Ulong?

Да, это так. Правда там несколько не так. Как и при работе со строками, для работы с переменными типа ULONG и DECIMAL используется спец. стек. Т.е., например, для выполнения такого кода UlongVar += 1 компилятор генерит код, в котором вызываются четыре стековые функции.

А насчет скорости выполнения — считайте сам. Тест для простого инкремента (Var += 1):

LONG примем за единицу, тогда для других типов увеличение времени обработки будет соответственно:

ULONG   — ~150 раз
DECIMAL — ~100 раз
REAL    — ~2 раза    !!!

Как видно ULONG — самый медленный. Медленнее даже чем DECIMAL! А вот от REAL, если честно я такой прыти не ожидал! Хотя чего удивляться — все операции с REAL производятся через мат.сопроцессор, а он — достойный помощник основному ядру проца.

Вот если бы ещё динамически создавать переменные…

Вот если бы ещё динамически создавать переменные…
Да все так-же, через RTL Клариона!
1. Выделяем память под новую переменную.
Для этого лучше воспользоваться этими процедурами:

!   Выделяет память и инициализирует ее двоичными нулями
  RTL::NewMem(UNSIGNED _Size),ULONG,NAME('Cla$NewMemZ')
!   Выделяет память и инициализирует ее пробелами
  RTL::NewStr(UNSIGNED _Size),ULONG,NAME('Cla$NewMemB')

_Size — размер выделяемой памяти, определяешь сам по типу переменной.
Возвращает адрес выделенного блока памяти. Читать далее

Обстановка C55F+ABC

Объясните пожалуйста следующую ситуацию и способы борьбы.

 MyVar   DECIMAL(20,0)

 MyVar = 1234567891 * 2
 STOP(MyVar) ! Выдает    -1825831514

а если написать так:

 MyVar = 1234567891
 MyVar = MyVar * 2
 STOP(MyVar) !То получим  2469135782

Может кто объяснит какого ….. он преобразует DECIMAL в LONG. Все становится просто, если вспомнить из доки, что базовым типом при вычислениях (если не задан явно тип операндов) принимается LONG.
Где в твоем примере сказано, что эти операнды имеют тип, отличный от LONG? Поэтому компилятор для вычисления данного примера использует временную переменную LONG-типа для приема результата вычисления. И уже после вычисления он эту LONG-переменную преобразует в DECIMAL.
Чтобы твой пример вычислялся правильно надо написать так:

MyVar = 1234567891,00 * 2,00

Вот теперь, при вычислении, для временного хранения результата будет использована REAL-переменная. Заметь — именно REAL! Поэтому, например, для расчета суммы лучше использовать две DECIMAL-переменные. Тогда не будет потерь в копейках и общая сумма всегда сойдется.

Кто-нить знает, что возвращает What()

Кто-нить знает, что возвращает сабж, если по всем признакам он должен вернуть массив? Что-то ведь возвращает. Но это вроде не массив, поскольку клара его как массив не распознает. Я попытался скормить его функции с параметром-массивом неопределенной длины. Она его выплюнула. Но и не переменная, поскольку попытка вывести его через message заканчивается плачевно.

WHAT() по полю-массиву возвращает ссылку на массив, описанный во внутреннем формате, принятом для нетипизированных переменных. Так называемые UFO-переменные. К сожалению, как либо легально воспользоваться данной инфой для работы с таким массивом невозможно!

Что то с драйверами…

Во-первых не True/False, а ‘on’/’off’:

 DRIVER('TOPSPEED', '/FULLBUILD = on | off' )
          [ State" = ] SEND(file, 'FULLBUILD [ = on | off ]' )
          [ State" = ] file{PROP:FULLBUILD} [ = on | off ]' )

А во-вторых, «This is the default behavior. Use the FULLBUILD driver string to modify this default behavior.» Имеется ввиду FULLBUILD = off. Так что «забыл» — это не страшно 🙂

Спасибо, что поправил! Но и ты не прав! Точнее — «врет» хелп.

На самом деле, со свойствами надо работать внимательно и избирательно. Некоторые нормально реагируют на False/True. К таким, в основном, относятся практически все свойства экранных элементов. Что же касается свойств файлов и View, то они, в основном, реагируют на НЕПУСТУЮ строку.

Т.е., например:
File{PROP:FullBuild} = True/False/’0’/’1’/’бла-бла’ — включает данное свойство файла.
Выключается свойство ТОЛЬКО так File{PROP:FullBuild} = ».

Так что, если какое-либо свойство у вас работает не так, как должно — проверьте, возможно вы включаете/выключаете его неверно.

… переменная MyValue так и остается UFO-переменной с типом ULONG …

>> Но! Именно из-за того, что в процедуре не происходит преобразование
>> типа, переменная MyValue так и остается UFO-переменной с типом ULONG.
>> А UFO-переменные ЛЮБОГО типа перед арифметическими операциями ВСЕГДА
>> преобразуются в тип REAL. Именно из-за этого преобразования значение
>> x80000001 становиться x80000000!!!
>> Ну а дальше — понятно: BXOR(x80000000,x80000000) = 0!

Если передать в процедуру LONG переменную она тоже UFO?
Но почему с ней все происходит корректно, если она тоже преобразуется к REAL?

Как я уже писал, в REAL-тип преобразуется любая переменная.
Другое дело, как это преобразование происходит! Хотя, в случае с LONG и ULONG переменными генерится абсолютно одинаковый код преобразования. Так что, или компилятор не прав и надо генерить другой код, или такие чудеса вытворяет сопроцессор, через чьи регистры и команды происходит это преобразование.