В общем, получилась такая штука для выдирания ИДшников:
FUNCTION QueryRows (strTableName, strTagName, nRowFrom, nNumRows, strKeyField, fForward)
CLOSE TABLES ALL
* IF USED ("GridProviderIDS")
* USE IN "GridProviderIDS"
* ENDIF
CREATE CURSOR GridProviderIDS (ID CHARACTER(9), RECN INTEGER(10))
TableAlias = "_" + strTableName
* IF USED ( (TableAlias) )
* ELSE
USE (strTableName) IN 0 ALIAS (TableAlias)
* ENDIF
SELECT (TableAlias)
* IF (UPPER (CDX (1)) != UPPER (strTableName)) OR (UPPER (TAG ()) != UPPER (strTagName))
SET ORDER TO TAG (strTagName) OF (strTableName)
* ENDIF
IF fForward = 1 THEN
nStep = 1
ELSE
nStep = -1
ENDIF
IF nRowFrom = 0 THEN
IF fForward = 1 THEN
GO TOP
ELSE
GO BOTTOM
ENDIF
ELSE
IF RECNO () != nRowFrom THEN
GOTO nRowFrom
ENDIF
SKIP nStep
ENDIF
NumFields = AFIELDS (arrFields)
UpKeyField = UPPER (strKeyField)
KeyFieldNum = 0
FOR CurField = 1 TO NumFields
IF UPPER (arrFields(CurField, 1)) = UpKeyField
KeyFieldNum = CurField
EXIT
ENDIF
ENDFOR
FOR Rec = 1 TO nNumRows
SELECT (TableAlias)
IF EOF ()
EXIT
ENDIF
IF BOF ()
EXIT
ENDIF
RN = RecNo ()
SCATTER TO ValArr
INSERT INTO GridProviderIDS ('ID','RECN') VALUES (ValArr(1,KeyFieldNum), RN)
SELECT (TableAlias)
SKIP nStep
ENDFOR
* SELECT (TableAlias)
* USE
RETURN SETRESULTSET ("GridProviderIDS")
ENDFUNC
* - звездочки - это однострочные комментарии - аналог "//" для 1С
При постоянном пейдждауне потребление процессора 30-40%. Память не съедается. Кое-что еще можно ускорить для уменьшения потребления CPU (например, цикл по полям можно сделать один раз, а не при каждом запросе ИДшников).
Напрягает одно: наличие CLOSE TABLES ALL. Без этой конструкции происходит слабая утечка памяти: 1-2 Мб за 2 года журнала. Вроде бы для утечки нет оснований. Курсор уничтожался командами:
* IF USED ("GridProviderIDS")
* USE IN "GridProviderIDS"
* ENDIF
Основная таблица не переоткрывалась в цикле - вот это было раскомментарено:
* IF USED ( (TableAlias) )
* ELSE
USE (strTableName) IN 0 ALIAS (TableAlias)
* ENDIF
То ли я конкретно плаваю в Фоксе и что-то конкретно не так делаю, то ли в OLE DB что-то не в порядке.
В принципе, с CLOSE TABLES ALL результат для локальной машине, ИМХО, достаточно приемлемый (особенно, если учесть, что я тестировал DEBUG-сборку провайдера). Однако, опасаюсь, что постоянные дерганья - закрытие/открытие таблиц может привести к тормозам при работе по сети...
Еще одно слабое место - SCATTER TO ValArr. Изначально эта хрень выглядела как SCATTER FIELDS strKeyField TO ValArr. Далее ИД забиралось из ValArr(1,1). Этот алгоритм хорошо работал со справочниками, но перестал на журнале. Вместо IDDoc мне подсовывался IDJOURN. Оказалось, что SCATTER складывает в массив вообще все поля текущей записи, а не только одно ключевое поле, как мне надо. У справочника ID идет первым полем, поэтому алгоритм работает. А у журнала IDDoc идет вторым полем, после IDJourn. То ли в OLE DB нельзя выбирать конкретные поля, то ли SCATTER FIELDS strKeyField понимает выражение буквально: выбрать поле с названием "strKeyField". В этом случае могли бы помочь такие вещи: SCATTER &strKeyField или SCATTER '&strKeyField', но Фокс ругается, что "Feature not available". Фокус с INSERT'ом так же не проходит:
INSERT INTO GridProviderIDS ('ID','RECN') VALUES (&strKeyField, RN)
Аналогично "Feature not available".