I have copied some code from an example for accessing an sqlite database. It uses an agent to get the returned rows:
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
The problem I have is that I would like to pass input_line to the procedure insert_into_db. The inline procedure used by execute_with_arguments isn't able to see any variables outside its scope, but I presume there must be a way to pass an extra parameter to it? Everything I have tried simply refuses to compile with syntax errors.
In this case, I simply want to add a database entry if it doesn't already exist, but I can easily see the case where I would want to send the returned row along with some extra data to another procedure, so it must be doable.
As you correctly point out, at the moment, local variables in Eiffel are not automatically passed into inline agents. The solution is to add explicit formal arguments to an inline agent and to pass the corresponding actual arguments to it.
The inline agent from the example can be adapted as follows (the outer context with the argument input_line
is omitted for brevity):
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)
In addition to the formal argument s
that will get the value of input_line
, you can see an explicit list of actual arguments (?, input_line)
. The question mark denotes an open argument, that will be passed to the agent by execute_with_arguments
as before. input_line
stands for a closed argument.
When the list has no closed arguments, as in the original code, it can be omitted. However, one could have written (?)
after the keyword end
of the inline agent in the original code to be absolutely explicit.