Вызов Eiffel sqlite с дополнительными параметрами

Я скопировал код из примера для доступа к базе данных sqlite. Он использует агент для получения возвращаемых строк:

    check_db (input_line: STRING)

    local

        df_db:       SQLITE_DATABASE
        df_db_query: SQLITE_QUERY_STATEMENT

        test_val: STRING

    do

        test_val := "whatever"

        create df_db.make_open_read_write ("Large.db")

        create df_db_query.make ("SELECT * FROM test_table WHERE test_val =%
                    % :TEST_VAL%
                    % ;", df_db)

        check df_db_query_is_compiled: df_db_query.is_compiled
            end

        df_db_query.execute_with_arguments (agent (returned_row: SQLITE_RESULT_ROW): BOOLEAN
                do
                    if returned_row.is_null (1) then
                        insert_into_db
                    end
                end,
            << create {SQLITE_STRING_ARG}.make  (":TEST_VAL", test_val) >>)

    end -- check_db

У меня проблема в том, что я хотел бы передать input_line процедуре insert_into_db. Встроенная процедура, используемая execute_with_arguments, не может видеть какие-либо переменные за пределами своей области, но я предполагаю, что должен быть способ передать ей дополнительный параметр? Все, что я пробовал, просто отказывается компилироваться с синтаксическими ошибками.

В этом случае я просто хочу добавить запись в базу данных, если она еще не существует, но я легко вижу случай, когда я хотел бы отправить возвращенную строку вместе с некоторыми дополнительными данными в другую процедуру, поэтому это должно быть выполнимо. .


person shakeshuck    schedule 27.03.2018    source источник


Ответы (1)


Как вы правильно заметили, на данный момент локальные переменные в Eiffel не передаются автоматически во встроенные агенты. Решение состоит в том, чтобы добавить явные формальные аргументы встроенному агенту и передать ему соответствующие фактические аргументы.

Встроенный агент из примера можно адаптировать следующим образом (внешний контекст с аргументом input_line для краткости опущен):

agent (returned_row: SQLITE_RESULT_ROW; s: STRING): BOOLEAN
    do
            -- `s` is attached to `input_line` here.
        if returned_row.is_null (1) then
            insert_into_db
        end
    end (?, input_line)

В дополнение к формальному аргументу s, который получит значение input_line, вы можете увидеть явный список фактических аргументов (?, input_line). Знак вопроса обозначает открытый аргумент, который будет передан агенту execute_with_arguments, как и раньше. input_line обозначает закрытый аргумент.

Когда список не имеет закрытых аргументов, как в исходном коде, его можно опустить. Однако можно было написать (?) после ключевого слова end встроенного агента в исходном коде, чтобы быть абсолютно явным.

person Alexander Kogtenkov    schedule 27.03.2018
comment
Спасибо, Александр, это исправило мои проблемы с компиляцией. Не желая слишком далеко отходить от темы, теперь похоже, что встроенная процедура не выполняется; он запускается только в том случае, если что-то возвращается? - person shakeshuck; 27.03.2018
comment
После быстрого теста оказалось, что встроенный код запускается только в том случае, если из базы данных возвращается результат. - person shakeshuck; 27.03.2018