I am trying to assign the output of a function to a variable, but I can’t do it. :(
I use Lua 5.3.4 and luarocks 3.2.1 (+luasql-postgres)
My script:
luasql = require "luasql.postgres"
value=arg[1]
current_time=os.date("%Y-%m-%d %H:%M:%S")
env = luasql.postgres()
con = assert (env:connect('postgres', 'postgres', 'postgres', '192.168.241.93','5432'))
function printvalues(res)
row = res:fetch ({}, "a")
while row do
print(string.format("%-12s", row.client_addr))
row = res:fetch (row, "a")
end
print()
end
res = assert (con:execute('select client_addr from pg_stat_replication order by replay_lag asc limit 1'))
--txn = res
a = {myfunc = printvalues(res)}
if a == '192.168.242.41' then
print("backend1")
elseif a == '192.168.241.76' then
print("backend2")
end
print(string.format("%-12s",a))
print(a)
Script result:
root#haproxy:/etc/haproxy# lua scripts/test.lua
192.168.1.76
table: 0x559fadf97080
table: 0x559fadf97080
Please tell me:
How can I assign the result of a function to a variable?
How to remove the empty line in the output of the function printvalues(res)
you need to make a return statement in the function body to return a value
the empty line in your example is the print() statement in the function printvalues
I see you are making a query using limit 1, since you will only get one value, the while loop statement is useless.
I hope this works for you
local luasql = require "luasql.postgres"
local env = luasql.postgres()
local con = assert (env:connect(
'postgres', 'postgres', 'postgres', '192.168.241.93', '5432'
))
local res = assert(con:execute(
'select client_addr from pg_stat_replication order by replay_lag asc limit 1'
))
local row = res:fetch({}, 'a')
local a = string.format('%-12s', row.client_addr)
res:close()
if a == '192.168.242.41' then
print('backend1')
elseif a == '192.168.241.76' then
print('backend2')
end
print(a)
but if you want an example with function:
local luasql = require "luasql.postgres"
local env = luasql.postgres()
local con = assert (env:connect(
'postgres', 'postgres', 'postgres', '192.168.241.93', '5432'
))
local res = assert(con:execute(
'select client_addr from pg_stat_replication order by replay_lag asc limit 1'
))
local function printvalues(res)
local row = res:fetch({}, 'a')
res:close()
return string.format('%-12s', row.client_addr)
end
local a = printvalues(res)
if a == '192.168.242.41' then
print('backend1')
elseif a == '192.168.241.76' then
print('backend2')
end
print(a)
try to use local keyword before variables, this will make them scope variables
Thank. I ended up using this script:
luasql = require "luasql.postgres"
env = luasql.postgres()
con = assert (env:connect('postgres', 'postgres', 'postgres','333.333.333.333','5432')) --master
backend = function(txn)
res = assert (con:execute('select client_addr from pg_stat_replication order by replay_lag asc limit 1'))
row = res:fetch ({}, "a")
while row do
ip = string.format("%-12s", row.client_addr)
row = res:fetch (row, "a")
end
result = "backend1"
if ip == '111.111.111.111' then
result = "backend1"
elseif ip == '222.222.222.222' then
result = "backend2"
end
return result
end
core.register_fetches("choose_backend", backend)
Related
i get this error at line 94 and i dont really know how to fix this error. if someone could help fix this error it would really help me.
-- a basic market implementation
local lang = vRP.lang
local cfg = module("cfg/markets")
local market_types = cfg.market_types
local markets = cfg.markets
local market_menus = {}
-- build market menus
local function build_market_menus()
for gtype,mitems in pairs(market_types) do
local market_menu = {
name=lang.market.title({gtype}),
css={top = "75px", header_color="rgba(0,255,125,0.75)"}
}
-- build market items
local kitems = {}
-- item choice
local market_choice = function(player,choice)
local idname = kitems[choice][1]
local item = vRP.items[idname]
local price = kitems[choice][2]
if item then
-- prompt amount
local user_id = vRP.getUserId(player)
if user_id ~= nil then
vRP.prompt(player,lang.market.prompt({item.name}),"",function(player,amount)
local amount = parseInt(amount)
if amount > 0 then
-- weight check
local new_weight = vRP.getInventoryWeight(user_id)+item.weight*amount
if new_weight <= vRP.getInventoryMaxWeight(user_id) then
-- payment
if vRP.tryFullPayment(user_id,amount*price) then
vRP.giveInventoryItem(user_id,idname,amount,true)
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.paid({amount*price})}, type = "success", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.not_enough()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.inventory.full()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.common.invalid_value()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
end)
end
end
end
-- add item options
for k,v in pairs(mitems) do
local item = vRP.items[k]
if item then
kitems[item.name] = {k,math.max(v,0)} -- idname/price
market_menu[item.name] = {market_choice,lang.market.info({v,item.description.. "\n\n" ..item.weight.. " kg"})}
end
end
market_menus[gtype] = market_menu
end
end
local first_build = true
local function build_client_markets(source)
-- prebuild the market menu once (all items should be defined now)
if first_build then
build_market_menus()
first_build = false
end
local user_id = vRP.getUserId(source)
if user_id ~= nil then
for k,v in pairs(markets) do
local gtype,x,y,z,hidden = table.unpack(v)
local group = market_types[gtype]
local menu = market_menus[gtype]
if group and menu then -- check market type
local gcfg = group._config
local function market_enter()
local user_id = vRP.getUserId(source)
if user_id ~= nil and vRP.hasPermissions(user_id,gcfg.permissions or {}) then
vRP.openMenu(source,menu)
end
end
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:close()
local function adminz_open()
TriggerClientEvent("chatMessage", source, "Min bror " .. gudsp)
end
local function market_leave()
vRP.closeMenu(source)
end
if hidden == true then
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
else
vRPclient.addBlip(source,{x,y,z,gcfg.blipid,gcfg.blipcolor,lang.market.title({gtype})})
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
end
vRP.setArea(source,"vRP:adminz",153.53675842285,-255.70140075684,51.399478912354,1,1.5,adminz_open,market_leave)
end
end
end
end
AddEventHandler("vRP:playerSpawn",function(user_id, source, first_spawn)
if first_spawn then
build_client_markets(source)
end
end)
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:read() is syntactic sugar for gudz["read"](gudz).
gudz["read"] is an indexing operation. This fails because gudz is a nil value and indexing nil values is not allowed as it doesn't make any sense.
That's like referring to a book page of a book that does not exist. You won't be able to read that page anyway.
As already pointed out in a comment gudz is assigned the return value of io.open( "vfs-core.txt", "r" ) which in this case is nil.
So let's refer to the Lua Reference Manual may its wisdom enlighten us.
io.open (filename [, mode])
This function opens a file, in the mode specified in the string mode.
In case of success, it returns a new file handle.
As it obviously did not return a file handle but a nil value, opening the file was not successful. So check path and file.
function GetCharacterName(source)
local xPlayer = QBCore.Functions.GetPlayer(source)
local name = xPlayer.PlayerData.charinfo.lastname
local name2 = xPlayer.PlayerData.charinfo.firstname
if xPlayer then
return name, name2
end
end
I'm trying to return the values of name and name2, however the return is only giving the first value. I'm newer to lua, and code in general, so just trying to learn
Additional places in which this function is called:
AddEventHandler("mdt:attachToCall", function(index)
local usource = source
local charname = GetCharacterName(usource)
local xPlayers = QBCore.Functions.GetPlayers()
for i= 1, #xPlayers do
local source = xPlayers[i]
local xPlayer = QBCore.Functions.GetPlayer(source)
if xPlayer.PlayerData.job.name == 'police' then
TriggerClientEvent("mdt:newCallAttach", source, index, charname)
end
end
TriggerClientEvent("mdt:sendNotification", usource, "You have attached to this call.")
end)
RegisterServerEvent("mdt:performVehicleSearchInFront")
AddEventHandler("mdt:performVehicleSearchInFront", function(query)
local usource = source
local xPlayer = QBCore.Functions.GetPlayer(usource)
if xPlayer.job.name == 'police' then
exports['ghmattimysql']:execute("SELECT * FROM (SELECT * FROM `mdt_reports` ORDER BY `id` DESC LIMIT 3) sub ORDER BY `id` DESC", {}, function(reports)
for r = 1, #reports do
reports[r].charges = json.decode(reports[r].charges)
end
exports['ghmattimysql']:execute("SELECT * FROM (SELECT * FROM `mdt_warrants` ORDER BY `id` DESC LIMIT 3) sub ORDER BY `id` DESC", {}, function(warrants)
for w = 1, #warrants do
warrants[w].charges = json.decode(warrants[w].charges)
end
exports['ghmattimysql']:execute("SELECT * FROM `player_vehicles` WHERE `plate` = #query", {
['#query'] = query
}, function(result)
local officer = GetCharacterName(usource)
TriggerClientEvent('mdt:toggleVisibilty', usource, reports, warrants, officer, xPlayer.job.name)
TriggerClientEvent("mdt:returnVehicleSearchInFront", usource, result, query)
end)
end)
end)
end
end)
There are two possible reasons.
name2 is nil
you're using the function call in a way that adjusts the number of return values to 1. This happens GetCharacterName(source) is not the last in a list of expressions or if you put that function call into parenthesis or you assign it to a single variable.
Edit:
Now that you've added examples of how you use that function:
local charname = GetCharacterName(usource)
In this case the result list of GetCharacterName is ajdusted to 1 value (name) as you only assingn to a single variable. If you want both return values you need two variables.
Either do it like so:
local lastName, firstName = GetCharactername(usource)
local charName = lastName .. ", " .. firstname
Then charName is "Trump, Donald" for example.
Or you return that name as a single string:
function GetCharacterName(source)
local xPlayer = QBCore.Functions.GetPlayer(source)
local name = xPlayer.PlayerData.charinfo.lastname
local name2 = xPlayer.PlayerData.charinfo.firstname
if xPlayer then
return name .. ", " .. name2
end
end
Then local charname = GetCharacterName(usource) will work
local name1, name2 = GetCharactersName()
I am facing a problem with the Lua script (please find it below) in the StackExchange.Redis.
I have dissected the code and got all of it working except for the last loop.
I get the following as error -- ERR Protocol error: expected '$', got ' '
The error message is quite generic in nature, as it gives me the same error message for different types of errors.
Can someone help me to figure out the problem?
var doesExist = (bool)db.ScriptEvaluate(#"
local function isDateInRange(DateStart, DateEnd, GivenDate)
if (GivenDate > DateStart and GivenDate < DateEnd)
then
return(true)
else
return(false)
end
end
--Fetch User's Category's StartDate and EndDate
local function IsCategoryDateValid()
local givenDate, DateStart, DateEnd
GivenDate = '2017-01-09'
StartDate = '2015-01-01'
EndDate = '2018-01-01'
local isDateValid
isDateValid = isDateInRange(StartDate, EndDate, GivenDate)
return(isDateValid)
end
-- Pass User, UserCategory and UserCategoryItem as parameters
local userNameKey = 'UserDetails:Invincible'
local userCategoryKey = 'UserCategories:Book'
local userCategoryItemKey = 'UserCategoryItems:Harry-Potter'
local userNameKeySplit = {}
local a = 1
for i in string.gmatch(userNameKey, '([^'..':'..']+)') do
userNameKeySplit[a] = i
a = a + 1
end
local userName = userNameKeySplit[2]
local userCategoryKeySplit = {}
local b = 1
for j in string.gmatch(userCategoryKey, '([^'..':'..']+)') do
userCategoryKeySplit[b] = j
b = b + 1
end
local userCategory = userCategoryKeySplit[2]
local userCategoryItemKeySplit = {}
local c = 1
for k in string.gmatch(userCategoryItemKey, '([^'..':'..']+)') do
userCategoryItemKeySplit[c] = k
c = c + 1
end
local userCategoryItem = userCategoryItemKeySplit[2]
-- Fetch Users, UserCategories and UserCategoryItems from the Redis DB
local userData = {'Invincible', 'User1', 'User2', 'User3'}
local userCategoryData = {'Book', 'Movie', 'Journals'}
local userCategoryItemData = {'Hardy-Boys', 'Harry-Potter', 'Shawshank-Redemption', 'The-Terminal'}
local msg
for i=1,#userData,1
do
if(userData[i] == userName)
then
for j=1,#userCategoryData,1
do
if(userCategoryData[j] == userCategory)
then
msg = true
break
else
msg = false
end
end
break
else
msg = false
break
end
end
return msg
",
new RedisKey[] { "UserDetails:" + "Invincible", "UserCategories:" + "Book", "UserCategoryItems:" + "Harry-Potter" });
We have a lengthy lua script. Please find it below after the problem description.
The logic of the script is to return true/false if all the 3 parameters match (UserName, UserCategory, UserCategoryItem)
The first part of the script splits the RedisKeys to fetch the UserName, UserCategory, UserCategoryItem. There is also a random function to test if ‘functions’ works in the Redis lua script. It works.
The second part of the script compares this values against the values in the Database. The values are hard-coded in the script. If all the values match it returns true else it returns false.
The two scripts run perfect when ran individually. But they throw an error when run together.
ISSUE/PROBLEM
All the three scripts run perfectly when run in an IDE. I use the SciTE IDE (an IDE for Lua for Windows envrionment)
The script creates an issue when run from the Stackexchange.Redis client.
The first two parts of the script (Part One and Part Two) run perfectly from the Stackexchange.Redis. It is only when they are combined in the third script (Part Three) does it throw an error.
As the error is generic in nature hence I am not able to further investigate the issue.
I have divided the script in Three parts. The final script combines the first two scripts.
var redis = ConnectionMultiplexer.Connect("localhost");
var db = redis.GetDatabase();
//PART ONE OF THE SCRIPT
var doesExist1 = (string)db.ScriptEvaluate(#"
local function isDateInRange(DateStart, DateEnd, GivenDate)
if (GivenDate > DateStart and GivenDate < DateEnd)
then
return(true)
else
return(false)
end
end
--Fetch User's Category's StartDate and EndDate
local function IsCategoryDateValid()
local givenDate, DateStart, DateEnd
GivenDate = '2017-01-09'
StartDate = '2015-01-01'
EndDate = '2018-01-01'
local isDateValid
isDateValid = isDateInRange(StartDate, EndDate, GivenDate)
return(isDateValid)
end
-- Pass User, UserCategory and UserCategoryItem as parameters
local userNameKey = 'UserDetails:DummyName'
local userCategoryKey = 'UserCategories:Book'
local userCategoryItemKey = 'UserCategoryItems:Harry-Potter'
local userNameKeySplit = {}
local a = 1
for i in string.gmatch(userNameKey, '([^'..':'..']+)') do
userNameKeySplit[a] = i
a = a + 1
end
local userName = userNameKeySplit[2]
local userCategoryKeySplit = {}
local b = 1
for j in string.gmatch(userCategoryKey, '([^'..':'..']+)') do
userCategoryKeySplit[b] = j
b = b + 1
end
local userCategory = userCategoryKeySplit[2]
local userCategoryItemKeySplit = {}
local c = 1
for k in string.gmatch(userCategoryItemKey, '([^'..':'..']+)') do
userCategoryItemKeySplit[c] = k
c = c + 1
end
local userCategoryItem = userCategoryItemKeySplit[2]
return(userName..' '..userCategory..' '..userCategoryItem)
",
new RedisKey[] { "UserCategoryItemNames:" + userModel.UserId });
//PART TWO OF THE SCRIPT
var doesExist2 = (bool)db.ScriptEvaluate(#"
local userName = 'DummyName'
local userCategory = 'Book'
local userCategoryItem = 'Harry-Potter'
-- Fetch Users, UserCategories and UserCategoryItems from the Redis DB
local userData = {'DummyName', 'User1', 'User2', 'User3'}
local userCategoryData = {'Book', 'Movie', 'Journals'}
local userCategoryItemData = {'Hardy-Boys', 'Harry-Potter', 'Shawshank-Redemption', 'The-Terminal'}
local msg
-- Loop through the fetched values and compare them with parameters; if all the parameters are found return true else return false
for i=1,#userData,1
do
if(userData[i] == userName)
then
for i=1,#userCategoryData,1
do
if(userCategoryData[i] == userCategory)
then
for i=1,#userCategoryItemData,1
do
if(userCategoryItemData[i] == userCategoryItem)
then
msg = true
break
else
msg = false
end
end
break
else
msg = false
end
end
break
else
msg = false
break
end
end
return(msg)
//PART ONE & TWO COMBINED OF THE SCRIPT
",
new RedisKey[] { "UserDetails:" + "DummyName", "UserCategories:" + "Book", "UserCategoryItems:" + "Harry-Potter" });
var doesExist3 = (bool)db.ScriptEvaluate(#"
local function isDateInRange(DateStart, DateEnd, GivenDate)
if (GivenDate > DateStart and GivenDate < DateEnd)
then
return(true)
else
return(false)
end
end
--Fetch User's Category's StartDate and EndDate
local function IsCategoryDateValid()
local givenDate, DateStart, DateEnd
GivenDate = '2017-01-09'
StartDate = '2015-01-01'
EndDate = '2018-01-01'
local isDateValid
isDateValid = isDateInRange(StartDate, EndDate, GivenDate)
return(isDateValid)
end
-- Pass User, UserCategory and UserCategoryItem as parameters
local userNameKey = 'UserDetails:DummyName'
local userCategoryKey = 'UserCategories:Book'
local userCategoryItemKey = 'UserCategoryItems:Harry-Potter'
local userNameKeySplit = {}
local a = 1
for i in string.gmatch(userNameKey, '([^'..':'..']+)') do
userNameKeySplit[a] = i
a = a + 1
end
local userName = userNameKeySplit[2]
local userCategoryKeySplit = {}
local b = 1
for j in string.gmatch(userCategoryKey, '([^'..':'..']+)') do
userCategoryKeySplit[b] = j
b = b + 1
end
local userCategory = userCategoryKeySplit[2]
local userCategoryItemKeySplit = {}
local c = 1
for k in string.gmatch(userCategoryItemKey, '([^'..':'..']+)') do
userCategoryItemKeySplit[c] = k
c = c + 1
end
local userCategoryItem = userCategoryItemKeySplit[2]
-- Fetch Users, UserCategories and UserCategoryItems from the Redis DB
local userData = {'DummyName', 'User1', 'User2', 'User3'}
local userCategoryData = {'Book', 'Movie', 'Journals'}
local userCategoryItemData = {'Hardy-Boys', 'Harry-Potter', 'Shawshank-Redemption', 'The-Terminal'}
local msg
-- Loop through the fetched values and compare them with parameters; if all the parameters are found return true else return false
for i=1,#userData,1
do
if(userData[i] == userName)
then
for i=1,#userCategoryData,1
do
if(userCategoryData[i] == userCategory)
then
for i=1,#userCategoryItemData,1
do
if(userCategoryItemData[i] == userCategoryItem)
then
msg = true
break
else
msg = false
end
end
break
else
msg = false
end
end
break
else
msg = false
break
end
end
return(msg)
",
new RedisKey[] { "UserDetails:" + "DummyName", "UserCategories:" + "Book", "UserCategoryItems:" + "Harry-Potter" });
Thank you for your patience and reading this much. I hope I have clarified the problem in detail. Please provide some help in solving the issue. Thank you.
I'm trying to get the name of all the file saved in two folders, the name are saved as :
1.lua 2.lua 3.lua 4.lua and so on
the folders name are :
first folder : "/const/"
second folder: "/virt/"
what I'm trying to do is only get the number of the files and this works but not in the right order, when I get the 17 file for example I get the 17th delivered from the function before the 15 and this causes for me a problem here the code of the function that I'm using :
local virt_path = "/virt/"
local const_path = "/const"
local fs = require "lfs"
local const = {}
for num = 1, (numberoffile)do -- numberoffile is predfined and can't be change
const[num] = assert(
dofile (const_path .. mkfilename(num)),
"Failed to load constant ".. num ..".")
end
local function file_number() --this is the function that causes me a headach
local ci, co, num = ipairs(const)
local vi, vo, _ = fs.dir(virt_path)
local function vix(o)
local file = vi(o)
if file == nil then return nil end
local number = file:match("^(%d+).lua$")
if number == nil then return vix(o) end
return tonumber(number)
end
local function iter(o, num)
return ci(o.co, num) or vix(o.vo, num)
end
return iter, {co=co, vo=vo}, num
end
As I said the function delive the need return values but not the right Arithmetic order.
any idea what I'm doing wrong here ?
I use my path[1] library.
1 We fill table with filenames
local t = {}
for f in path.each("./*.lua", "n") do
t[#t + 1] = tonumber((path.splitext(f)))
end
table.sort(t)
for _, i in ipairs(t) do
-- do work
end
2 We check if files exists
for i = 1, math.huge do
local p = "./" .. i .. ".lua"
if not path.exists(p) then break end
-- do work
end
[1] https://github.com/moteus/lua-path