Столкнулся со следующей проблемой:
Есть процедура в которой обрабатывается глобальная очередь
GloQueue QUEUE,TYPE ID LONG END MyQueue &GloQueue, THREAD
В пределах одного модуля пишу процедуру с описанием myProc ( Queue, long, long ) вызываю ее из этого же модуля — myProc ( MyQueue, MyQueue.ID, curNumber )
myProc ( _queue, _id, _num ) FieldQueue ANY CODE FieldQueue &= What( _queue, 1 ) FieldQueue = _num _id = _num get ( _queue, _id ) if errorcode () then add ( _queue ) end
Получаем, что если сначала вызываем эту процедуру со значениями 3,4,5, то результат records( _queue ) даст 3 записи. При повторном вызове со значениями 1,2, получаем errorcode () = 0, т.е. что-то находит c этими значениями, хотя их там нет.
Естественно! Внимательно читайте доку!
Если вторым параметром оператора GET() для очереди стоит переменная, которая не является полем этой очереди, то считается, что эта переменная содержит НОМЕР записи, которую надо считать. Поэтому:
_id = 1: GET(_queue,_id) аналогичен GET(_queue,1)
_id = 2: GET(_queue,_id) аналогичен GET(_queue,2)
И первая и вторая запись в очереди уже есть, поэтому и нет никакой ошибки!
Если в этой же процедуре написать напрямую значения очереди:
MyQueue.ID = _num get ( MyQueue, MyQueue.ID ) if errorcode () then add ( MyQueue ) end
то все работает нормально.
И это — правильно!
Пробовал в описании процедуры писать *Queue, не помогает. Первоначально под очередь память выделяю. Это не поможет. Надо тогда-уж прямо написать:
MAP MyProc(*GloQueue _Queue, LONG _Id, LONG _Num) END MyProc PROCEDURE(*GloQueue _Queue, LONG _Id, LONG _Num) ... _Queue.Id = _Num GET(_Queue,+_Queue.Id) ...
Что может быть?
Если, все же, в процедуре может идти работа с разными очередями, а в качестве ключевого поля задается его номер и значение, то решить данную проблему можно двумя вариантами:
1. Использовать внутренние функции работы с очередью:
MAP MyProc(*Queue _Queue, LONG _KeyFieldNo, ? _KeyFieldVal) MODULE('Clarion RTL') GetQue(*QUEUE,LONG,LONG=0),LONG,PROC,RAW,NAME('Cla$GETqueuekey') AddQue(*QUEUE,LONG,LONG=0),LONG,PROC,RAW,NAME('Cla$ADDqueuekey') END END MyProc PROCEDURE(*Queue _Queue, LONG _KeyFieldNo, ? _KeyFieldVal) KeyField ANY SaveQue &STRING Code KeyField &= WHAT(_Queue,ABS(_KeyFieldNo)) if ~(KeyField &= Null) SaveQue &= NEW(STRING(SIZE(_Queue))) ! Выделяем буфер KeyField = _KeyFieldVal SaveQue = _Queue ! Сохраняем запись GetQue(_Queue,_KeyFieldNo) if ErrorCode() _Queue = SaveQue ! Восстанавливаем запись AddQue(_Queue,_KeyFieldNo) . Dispose(SaveQue) ! Убиваем буфер . Return
Заметь, что в операторе WHAT() используется ABS(). Дело в том, что номер ключевого поля можно задать отрицательным. Для функций GetQue/AddQue это равнозначно:
GET(_Queue,-_Queue.ID) и ADD(_Queue,-_Queue.ID)
Кроме того, желательно после ошибочного оператора GET() и перед добавлением новой записи восстановить значение буфера записи очереди. Дело в том, что в прежних версиях языка, по недосмотру разработчиков, уже была очистка буфера после ошибочного GET(). Кто его знает, что будет дальше:) Лучше перестраховаться и не зависеть от внутреннего поведения той или иной функции! В принципе, при объявлении функций GetQue/AddQue можно задать до (кажется, не помню точно) 32 параметров (ключевых полей). Но последний параметр всегда должен быть равен 0!
2. Использовать для всего этого и многого другого библиотеку DynaLib.