I am new to Lua, and this is an elementary question.
I a Lua script, I am querying the Postgress DB for two records via Freeswitch dbh.
I am able to set the first value as a local variable.
I am stuck at how to set the second value as a variable.
local dbh = Database.new('system');
local settings = Settings.new(dbh, A, B);
local sql = "SELECT A, B FROM TABLE WHERE A = '" .. A.."'";
local A = dbh:first_value(sql); --this gets saved correctly
local B = WHAT DO PUT HERE? ; -- Perhaps, I need to create an array instead?
dbh:release()
If you only want a specific row you should do this in the SQL command.
Alternatively you can query the entire table and run through the rows of the result.
I don't know freeswitch but that's what I found here:
https://freeswitch.org/confluence/display/FREESWITCH/Lua+API+Reference
dbh:query("query", function()) takes the query as a string and an optional Lua callback function that is called on each row returned by
the db. The callback function is passed a table representation of the
current row for each iteration of the loop.
Syntax of each row is: { ["column_name_1"] = "value_1", ["column_name_2"] = "value_2" }.
If you (optionally) return a number other than 0 from the
callback-function, you'll break the loop.
In order to use this you should learn how to define functions and how to use function values. Then it should be obvious what to do.
Maybe there is also a function that returns the query result as a table. At least that is the case for many other database interfaces. Ideally you should read the manual of the freeswitch Lua API first. Then you know what commands exist. Together with the Lua manual you'll know how to use them.
Related
local a = {'1'}
b = {'2'}
print('--------a:', a) --------a: table: 002411A0
print('--------b:', b) --------b: table: 005BC470
how can I get like: a.lua:1 in table a
or a.lua:2 in table b
while I know the table address (002411A0)
my lua environment is lua5.1, I don't know if I need to read the source or compiled of lua5.1?
If you are prepared to declare your tables with a helper function, called, say logger, you can achieve your goal.
The idea is to record the line in a virtual table field __line. In the example below I do it using __index metamethod, but you can simply add a field to the created table.
The line number is obtained by debug.getinfo (2).currentline. The choice of 2 is determined by the call stack depth in my example.
local function logged (t)
local line = debug.getinfo (2).currentline
return setmetatable (t, {
__index = function (_, key)
if key == '__line' then
return line
end
end
})
end
local a = logged {'1'}
print (a.__line) -- 12
b = logged {'2'}
print (b.__line) -- 14
There is no way to get a line where the table is defined by using its address (as the line in the source code and the address in memory have no relationship). What you can do is to parse the source code of your script and find where the definition of the table is, but I'm not sure what use it's going to have for you. Maybe you can describe what you are trying to do?
If you indeed want to find where the table is defined, you can use something like metalua that builds abstract syntax tree (AST) of your code fragment that you can then traverse to find where a particular table is defined.
Another option is to parse the output of luac compiler, which will allow you to find what line the NEWTABLE command for a particular table is on.
Our task is create a table, and read values to the table using a loop. Print the values after the process is complete. - Create a table. - Read the number of values to be read to the table. - Read the values to the table using a loop. - Print the values in the table using another loop. for this we had written code as
local table = {}
for value in ipairs(table) do
io.read()
end
for value in ipairs(table) do
print(value)
end
not sure where we went wrong please help us. Our exception is
Input (stdin)
3
11
22
abc
Your Output (stdout)
~ no output ~
Expected Output
11
22
abc
Correct Code is
local table1 = {}
local x = io.read()
for line in io.lines() do
table.insert(table1, line)
end
for K, value in ipairs(table1) do
print(value)
end
Let's walk through this step-by-step.
Create a table.
Though the syntax is correct, table is a reserved pre-defined global name in Lua, and thus cannot should not be declared a variable name to avoid future issues. Instead, you'll need to want to use a different name. If you're insistent on using the word table, you'll have to distinguish it from the function global table. The easiest way to do this is change it to Table, as Lua is a case-sensitive language. Therefore, your table creation should look something like:
local Table = {}
Read values to the table using a loop.
Though Table is now established as a table, your for loop is only iterating through an empty table. It seems your goal is to iterate through the io.read() instead. But io.read() is probably not what you want here, though you can utilize a repeat loop if you wish to use io.read() via table.insert. However, repeat requires a condition that must be met for it to terminate, such as the length of the table reaching a certain amount (in your example, it would be until (#Table == 4)). Since this is a task you are given, I will not provide an example, but allow you to research this method and use it to your advantage.
Print the values after the process is complete.
You are on the right track with your printing loop. However, it must be noted that iterating through a table always returns two results, an index and a value. In your code, you would only return the index number, so your output would simply return:
1
2
3
4
If you are wanting the actual values, you'll need a placeholder for the index. Oftentimes, the placeholder for an unneeded variable in Lua is the underscore (_). Modify your for loop to account for the index, and you should be set.
Try modifying your code with the suggestions I've given and see if you can figure out how to achieve your end result.
Edited:
Thanks, Piglet, for corrections on the insight! I'd forgotten table itself wasn't a function, and wasn't reserved, but still bad form to use it as a variable name whether local or global. At least, it's how I was taught, but your comment is correct!
I am trying to write a Lua script that will return multiple keys back from a Redis DB. The script I am trying to run is:
script load "local values = redis.call('MGET', unpack(ARGV)); local results = {}; for i, key in ipairs(ARGV) do results[key] = values[i] end; return results"
I would then try and run it using evalsha (whatever the sha number is that it returns) 0 dog cat (where dog and cat are two keys I have saved in my DB).
Ideally, it would return "woof" "meow" as those are the values stored in the keys dog and cat. For some reason, this script will always return an empty list or set, and I do not understand why. Any help figuring it out would be appreciated!
results should be an array, i.e. indexed with number, NOT string. See conversion between Lua and Redis data types for details.
In order to make it work, change results[key] = values[i] into results[i] = values[i].
Also, in fact, you can just return values, there's no need to convert values to results.
Is it possible to check if some object is really element of specified table? I tried to use debug.getfenv(o) but didn't work.
someTable = {}
someTable.someValue = "Some String"
--gettable(someTable.someValue)
--so that could return table that stores someValue: someTable
getfenv is so named because it returns a function's environment. Because only functions have environments.
Values in Lua have no particular knowledge of which tables that they're in. If you need to know that, you'll have to keep track of it yourself.
I made an interactive command shell which is operating by Lua interpreter. User input some command, shell calls something like lua_dostring to execute it. I want to allow users to define their own functions in arbitrary table, and save it to separated storage (like a file) automatically. According to the manual, I can get exact source code input by user with lua_Debug.
It looks possible to save the functions sources to some files after all execution done. But I want to save automatically when it's just added/remove.
Can I detect the moment of some value is just added to a table?
Yes. If you have a table tbl, every time this happens:
tbl[key] = value
The metamethod __newindex on tbls metatable is called. So what you need to do is give tbl a metatable and set it's __newindex metamethod to catch the input. Something like this:
local captureMeta = {}
function captureMeta.__newindex(table, key, value)
rawset(table, key, value)
--do what you need to with "value"
end
setmetatable(tbl, captureMeta);
You will have to find a way to set the metatable on the tables of interest, of course.
Here's another way to do this with metatables:
t={}
t_save={}
function table_newinsert(table, key, value)
io.write("Setting ", key, " = ", value, "\n")
t_save[key]=value
end
setmetatable(t, {__newindex=table_newinsert, __index=t_save})
Here's the result:
> t[1]="hello world"
Setting 1 = hello world
> print(t[1])
hello world
Note that I'm using a second table as the index to hold the values, instead of rawset, since __newindex only works on new inserts. The __index allows you to get these values back out from the t_save table.