带有额外参数的 Eiffel sqlite 调用

Eiffel sqlite call with extra parameters

我从一个示例中复制了一些代码来访问 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 使用的内联过程无法看到其范围之外的任何变量,但我认为必须有一种方法可以将额外的参数传递给它?我尝试过的一切都只是拒绝编译并出现语法错误。

在这种情况下,我只是想添加一个数据库条目(如果它尚不存在),但我可以很容易地看到我想将返回的行连同一些额外数据发送到另一个过程的情况,所以它一定是可行的。

正如您正确指出的那样,目前,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)

除了将获得 input_line 值的形式参数 s 之外,您还可以看到实际参数的显式列表 (?, input_line)。问号表示一个开放的论点,它将像以前一样由 execute_with_arguments 传递给代理。 input_line代表一个封闭的论点。

当列表没有闭合参数时,如在原始代码中,可以省略。但是,可以在原始代码中的内联代理的关键字 end 之后写 (?) 以绝对显式。