-- query.lua

-- local argcheck = require "argcheck"
local l = require "lang".l
local fn = require "fn"
local util = require "util"
local json = require "json"
local db = require "database"
local peg = require "peg"
local selection = require "selection"
local execute = require "execute"
local script = require "script_old"
local dext, rest -- delay load

local loc = {}
loc.traceQuerySql = false

local f, conn
local function init(conn_)
	conn = conn_ or db.connect("postgre")
	f = db.fieldTable()
end

--[[ -- not in use
local function saveStructure(parameter)
	local connSave = parameter.conn or parameter.database or conn
	local err = db.structureTableToSelection(connSave, parameter)
	if err then
		return nil, l("save was failed: '%s'", tostring(err))
	end
end
--]]
local lastQueryJsonName
local function queryJsonName()
	return lastQueryJsonName
end

local function queryJson(query, parameter, option)
	local err
	local queryTable
	local queryJsonName
	local origQueryParam = query
	if type(query) == "string" then
		-- if parameter then and parameter.show_sql == true then
		-- 	queryJsonName = query
		-- end
		queryJsonName = query
		if peg.startsWith(query, "query/") then
			query = util.prf(query, "no-cache")
		else
			query = util.prf("query/"..query, "no-cache")
		end
	end
	if not rest then
		rest = require "rest"
	end
	if not query or util.tableIsEmpty(query) then
		return rest.answerError(l("query '%s' was not found or json was invalid", tostring(origQueryParam))) -- SHOULD return ret.err
	elseif not(query.field or (parameter and (parameter.field or parameter.columns))) then
		return rest.answerError(util.parameterError("field or columns")) -- SHOULD return ret.err
	elseif query.query == nil then
		return rest.answerError(util.parameterError("query or select")) -- SHOULD return ret.err
	elseif not (parameter and parameter.columns) and (not query.field or #query.field < 1) and (not parameter or not parameter.field or #parameter.field < 1) then
		return rest.answerError(l"parameter field count is smaller than 1") -- SHOULD return ret.err
	end
	local conn = nil

	if parameter then
		parameter = util.cloneShallow(parameter) -- do not change the original parameter
	end

	-- paramter can contain columns-definition
	if parameter and parameter.columns then -- and not query.field, -- parameter always overrides field -tag
		query = util.cloneShallow(query) -- do not change the original query
		if type(parameter.columns) == "string" then
			local prf = util.prf(parameter.columns)
			parameter.columns = prf.columns
		end
		if parameter.columns then
			parameter.field = util.objectFieldToArr(parameter.columns, "field")
		end
	end

	-- copy query.parameter keys to parameter
	if query.parameter then
		if not parameter then
			parameter = query.parameter
		else
			for key, val in pairs(query.parameter) do
				if parameter[key] == nil then
					parameter[key] = val
				end
			end
		end
	end

	if query.run then
		if not parameter then
			parameter = {}
		end
		local _, err = execute.runCode(query.run, {parameter = parameter})--query) --parameter) ["return"] = query.return,
		if err then
			util.printError(l("error in calling code '%s':  '%s'", tostring(json.toJson(query.run)), err))
		end
	end

	if type(query.map_parameter) == "table" then
		parameter = parameter or {}
		err = execute.runCode(query.map_parameter, parameter, parameter)
		if err then
			return  {error = l"error in query 'map_parameter': "..err}
		end
	end

	if parameter then
		if parameter.show_sql == true then
			if queryJsonName == nil then
				queryJsonName = db.preferenceFromJsonName() -- our best quess
			end
			-- io.write(l("- query json '%s'", queryJsonName))
			db.showSql(true)
		end
		if type(parameter.selection_id) == "string" and parameter.selection_id ~= "" then
			local sel = selection.loadSelection(parameter.selection_id)
			if sel and sel.record_id then
				parameter.selection = sel.record_id
			else
				return rest.answerError(l("selection id '%s' was not found", parameter.selection_id))
			end
		end
		if type(parameter.conn) == "table" then
			conn = parameter.conn
		end
	end
	if not parameter then
		parameter = {}
	end
	parameter.queryJsonName = queryJsonName or query.name
	lastQueryJsonName = parameter.queryJsonName
	-- util.printRed(queryJsonName)
	local ret = db.queryJson(conn, query, parameter, nil, query.option)
	if parameter and parameter.show_sql == true then
		db.showSql(false)
	end

	if ret == nil or ret.data == nil or type(ret.data) ~= "table" then -- or util.tableIsEmpty(ret.data) == true then
		if ret == nil then
			ret = {}
		end
		ret.data = {}
	end
	-- if ret.info and ret.info.error then
	-- 	print(l("query json returned error '%s'", ret.info.error))
	-- end
	if type(query["return"]) == "table" then
		for key, val in pairs(query["return"]) do
			ret[key] = val
		end
	end

	if ret and parameter.to_json and ret.data and #ret.data > 0 then
		fn.iter(ret.data):each(function (rec)
			for key, val in pairs(rec) do
				if peg.endsWith(key, "_json_data") then
					rec[key] = json.fromJson(val)
				end
			end
		end)
	end
	-- create structured data if query.structure -tag exist
	if ret and query.structure and ret.data and #ret.data > 0 then
		local tablePrefix = next(ret.data[1]) -- tablePrefix = main data first field, todo: use query main table tag
		tablePrefix = db.tablePrefix(tablePrefix)
		local subParam = util.cloneShallow(parameter) -- safer to clone, do not change the original
		if #query.structure > 0 then
			local recordIdArr = {}
			fn.iter(query.structure):each(function(subQuery)
				local subTbl = {}
				subTbl[1] = ret.data -- newData[tablePrefix] -- original main data
				local maxDepth = subQuery.depth or 1
				local subQueryName = subQuery.query
				for depth = 1, maxDepth do -- do queries as long as there is data or maxDepth has been reached
					-- set query parameter
					if subQuery.parameter then
						fn.iter(subQuery.parameter):each(function(param)
							subParam[param.tag] = nil
							if param.tag and param.field then -- later param.value or something else
								recordIdArr[depth] = util.fieldValueToArray(subTbl[depth], param.field)
								if #recordIdArr[depth] > 0 then
									subParam[param.tag] = recordIdArr[depth]
								end
							end
						end)
					end

					-- do query
					subParam.columns = subQuery.columns
					local ret, err
					ret, err, tablePrefix = queryJson(subQueryName, subParam) -- tablePrefix changes to query table
					subTbl[depth + 1] = ret and ret.data -- ret.data may be nil
					if not subTbl[depth + 1] then
						break
					end
				end -- end: for depth = ...

				-- link lower level records to upper level records
				for depth = #subTbl, 2, -1 do
					fn.iter(subTbl[depth]):each(function(rec)
						local parentTbl = subTbl[depth - 1]

						--[[ create subtable array for every parent even if it does not contain any subrecords
						fn.iter(parentTbl):each(function(parentRec)
							if not parentRec[tablePrefix] then
								parentRec[tablePrefix] = {json.jsonNull()} -- how to force this to be an json array instead of object?
							end
						end)
						--]]

						local parentRec = util.arrayRecord(rec[subQuery.child_field], parentTbl, subQuery.parent_field)
						if not parentRec then
							util.printError(l("parent record was not found, id '%s'", tostring(rec[subQuery.child_field])))
						else
							if not parentRec[tablePrefix] then
								parentRec[tablePrefix] = {}
							end
							parentRec[tablePrefix][#parentRec[tablePrefix] + 1] = rec
						end
					end)
				end

			end)
			-- newData, ret.error = db.recordArraysToStructure(newData)
		end
		ret.table = tablePrefix
	end
	if query.field and query.field[1] then
		queryTable = db.tablePrefix(query.field[1])
	end
	--[[if err then
		-- ret may be nil
		ret.error = err
	end]]
	return ret, err, queryTable
end


local function queryRec(query, parameter)
	local rec = {}
	-- local tag = (parameter and parameter.return_tag) or "rec"
	local option = (parameter and parameter.option) or nil
	local qryRet, err, tbl = queryJson(query, parameter)
	if err then
		return nil, err
	elseif qryRet == nil or qryRet.data == nil or type(qryRet.data) ~= "table" or qryRet.data[1] == nil then
		if tbl and option and peg.find(option, "empty-record") > 0 then
			local newRec = db.newRecord(nil, tbl, "all-fields")
			if newRec and newRec[tbl] and newRec[tbl][1]then
				rec = newRec[tbl][1]
			else
				return {}
			end
		else
			return {}
		end
	elseif qryRet.data[1] then
		rec = qryRet.data[1]
	else
		return {} -- or nil?, warn of no-data?
	end
	if parameter and parameter.default then -- override default values
		if type(parameter.default) ~= "table" then
			err = l("parameter.default type '%s' is not a table", type(parameter.default))
			util.printError(err)
		else
			for key, val in pairs(parameter.default) do
				rec[key] = val
			end
		end
	end
	-- "script": ["timec_employee_id"]
	if parameter and parameter.script then
		script.runScript({table = tbl, data = {rec}, field_name = parameter.script})
		--[[
		local ret = script.runScript({rec = rec, table = tbl, field_name = parameter.script})
		if ret.rec then
			rec = ret.rec
		end
		]]
	end
	rec.__keep_value = true
	return {rec = rec, error = err}
end

local function queryJsonData(query, parameter)
	local ret = queryJson(query, parameter)
	if ret and ret.data ~= nil and type(ret.data) == "table" then -- and util.tableIsEmpty(ret.data) == false then
		return ret.data, ret and ret.error
	else
		return {}, ret and ret.error
		-- info
		-- return rest.answerError(l"parameter field count is smaller than 1")
	end
end

local function queryRecord(conn, table, recordId)
	if table == nil then
		return nil, l"'table' parameter is missing"
	elseif recordId == nil then
		return nil, l"'recordId' parameter is missing"
	end
	if not f then
		f = db.fieldTable()
	end
	local ret
	local recordIdField = db.uuidFieldConstant(table)
	if type(recordId) == "string" then
		db.query(conn, "", f[recordIdField], "=", recordId)
		ret = db.selectionToRecordTable(conn, f[table])
		ret = ret[1]

	elseif type(recordId) == "table" then
		db.query(conn, "", f[recordIdField], "in", recordId)
		ret = db.selectionToRecordTable(conn, f[table])
	end
	return ret
end

local function querySql(param)
  -- util.printTable(param, "query.lua/querySql - param")
	-- MUST add extra rights-check to this or remove completely!
	if type(param.sql) ~= "string" then
		return rest.answerError(util.parameterError("sql", "string"))
	--[[ field and field_type may be nil
	elseif type(param.field) ~= "table" then
		return rest.answerError(util.parameterError("field", "table"))
	elseif type(param.field_type) ~= "table" then
		return rest.answerError(util.parameterError("field_type", "table"))
		]]
	end
	if loc.traceQuerySql then
		util.printTable(param)
	end
	if not conn then
		init()
	end
	local data, info = db.sqlExecuteUnsafeArray(conn, param.sql, param.field, param.field_type, param.query_name or "") -- param.fieldName, param.fieldType)
	if info.arr_ap_json then
		data.text_data = true
		return data 
	end
	if not dext then
		dext = require "db/db_external"
	end
	dext.querySqlAlter(param, data, info)

	return {info=info, data=data} -- {error="sql query not done: "..tostring(param.sql)}
end

local function getSessionParameter(param)
	local ret = {}
	if param.parameter then
		-- if type(param.parameter.record_id) == "string" and param.parameter.record_id ~= "" then
		if type(param.parameter.session_id) == "string" and param.parameter.session_id ~= "" then
			local sessionJson = selection.loadSelection(param.parameter.session_id)
			if sessionJson and type(sessionJson.parameter) == "table" then
				sessionJson = util.tableCombine(sessionJson, sessionJson.parameter) -- combine session.parameter to main level
				sessionJson.parameter = nil
			end
			sessionJson.parameter = nil
			--[[if ret then
				ret = util.tableCombine(ret, sessionJson, "no-error")
			else
				ret = sessionJson
			end]]
			ret = sessionJson
			ret.session_record_id = param.parameter.session_id
			if sessionJson and sessionJson.table and sessionJson.record_id and #sessionJson.record_id >= 1 then
				ret[sessionJson.table.."_record_id"] = sessionJson.record_id[1] -- set first record id
			end
		end
	end
	return ret
end

local function query(param)
	local function queryGrid(grid, parameter)
		if type(grid) ~= "table" and type(grid) ~= "string" then
			return util.parameterError("grid", "table or string")
		end
		local ret = {}
		local function queryGridRec(grid)
			if grid.grid then
				return fn.util.callArrayParamRecursive(grid.grid, queryGridRec, "table", "no-cache")
			end
			if type(grid.name) ~= "string" then
				return util.parameterError("name", "string")
			elseif grid.name == "" then
				return l("preference '%s' grid name is empty", db.preferenceFromJsonName())
			elseif type(grid.query) ~= "string" and type(grid.query) ~= "table" then
				return util.parameterError("query", "string or table")
			elseif grid.query == "" then
				return l("preference '%s' grid query is empty", db.preferenceFromJsonName())
			elseif type(grid.columns) ~= "string" and type(grid.columns) ~= "table" then
				return util.parameterError("columns", "string or table")
			elseif grid.columns == "" then
				return l("preference '%s' grid columns is empty", db.preferenceFromJsonName())
			end
			local columns, queryParam, err
			if type(grid.columns) == "table" then
				if grid.columns.columns then
					columns = grid.columns
				else
					columns = {columns = grid.columns}
				end
			else
				columns, err = util.prf(grid.columns, "no-cache")
			end
			if util.tableIsEmpty(columns) then
				return err or l("preference '%s' parameter columns '%s' preference was not found", db.preferenceFromJsonName(), grid.columns)
			end
			if type(grid.query) == "table" then
				queryParam = grid.query
			else
				queryParam, err = util.prf(grid.query, "no-cache")
			end
			if util.tableIsEmpty(queryParam) then
				return err or l("preference '%s' parameter query '%s' preference was not found", db.preferenceFromJsonName(), grid.query)
			end
			queryParam.field = util.objectFieldToArr(columns.columns, "field")
			local sel = queryJson(queryParam, parameter)
			if sel == nil then
				return l("preference '%s' query error: 'query returned nil'", db.preferenceFromJsonName())
			end
			if type(sel) == "string" or sel.error then
				return l("preference '%s' query error: '%s'", db.preferenceFromJsonName(), sel.error or sel)
			end
			ret[grid.name] = {data = sel.data, info = sel.info, columns = columns.columns, options = columns.options}
		end
		local err = fn.util.callArrayParamRecursive(grid, queryGridRec, "table", "no-cache")
		if type(err) == "string" then
			return {error = err}
		end
		return ret
	end

	local function queryPreference(param1)
		if type(param) ~= "table" and type(param) ~= "string" then
			return util.parameterError("param", "table or string")
		end
		-- local ret = {}
		local errTxt
		local infiniteLoopPreventArray = {}
		local function queryPref(param)
			if type(param) == "string" and peg.endsWith(param, ".json") then
				if infiniteLoopPreventArray[param] then
					errTxt = l("preference '%s' has infinite loop,'%s' has been loaded before", param1, param)
					return errTxt
				end
				infiniteLoopPreventArray[param] = true
				local prf2, err = util.prf(param, "no-cache")
				if util.tableIsEmpty(prf2) then
					errTxt = err or l("preference '%s' was not found", param)
					return errTxt
				end
				return prf2
			end
			return param
		end
		local function queryPreferenceRec(param)
			local prf = queryPref(param)
			if type(prf) == "table" then
				for key, val in pairs(prf) do
					if key ~= "name" and key ~= "info" and type(val) == "string" and peg.endsWith(val, ".json") then
						local prf2 = queryPref(val)
						if errTxt then
							return errTxt
						end
						prf[key] = prf2
						queryPreferenceRec(prf[key]) -- recursive call
					end
				end
			end
			return prf
		end
		local ret = queryPreferenceRec(param1) -- fn.util.callArrayParamRecursive(param1, queryPreferenceRec, "table", "no-cache")
		if type(ret) == "string" then
			return {error = ret}
		end
		return ret
	end

	-- db.preferenceNameToPopupTable()
	local prf, err
	if type(param.name) ~= "string" then
		return util.parameterError("name", "string")
	end
	if param.query_json then
		param.name, err = json.fromJson(param.query_json)
	elseif not peg.endsWith(param.name, ".json") then
		param.name = param.name..".json"
	end
	if param.table_query then -- query given as table, not as parameter name that will be loaded from prf
		prf = param.table_query
	else
		prf, err = queryPreference(param.name)
		if prf and prf.error then
			return prf
		end
	end
	-- util.prf(param.name, "no-cache")
	if util.tableIsEmpty(prf) then
		return err or l("preference '%s' was not found", param.name)
	end
	local ret = {}

	local sessionParam = getSessionParameter(param)
	if param.parameter then
		param.parameter = util.tableCombine(param.parameter, sessionParam, "no-error")
	end

	if prf.data then
		ret.data = prf.data -- parse possible data tags json?
	end
	if prf.run then
		-- main level run tag may set values only to data or parameter
		ret.data = ret.data or {}
		local _, err = execute.runCode(prf.run, {data = ret.data, parameter = param.parameter})
		if err then
			return {error = l("error in query '%s' when calling code '%s':  '%s'", tostring(prf.name), tostring(json.toJson(ret.rec.run)), err)}
		end
	end

	if param["return"] then
		local var = peg.parse(param["return"], ".", 1)
		local tag = peg.parse(param["return"], ".", 2)
		if param.to_json == true then
			prf = json.toJson(prf)
		end
		if ret[var] == nil then
			ret[var] = {}
		end
		if var == "grid" then
			ret.grid.name = tag
			for key, val in pairs(prf) do
				ret.grid[key] = val
			end
			if param.query then -- override with rest call query
				ret.grid.query = param.query
			end
			if param.columns then
				ret.grid.columns = param.columns
			end
			if param.options then
				ret.grid.options = param.options
			end
		else
			ret[var].__keep_value = true
			ret[var][tag] = prf
		end
	end

	if param.rec_field ~= nil then
		ret.rec = {}
		ret.rec[param.rec_field] = json.toJson(prf)
		ret.rec.__keep_value = true
	else
		if prf.hdr ~= nil then
			-- do this?
		end

		if ret.rec == nil and prf.rec ~= nil then
			ret.rec = prf.rec -- queryPreference(prf.rec, "rec")
		end
		if ret.rec then
			ret.rec = util.tableCombine(ret.rec, sessionParam, "no-error")
		end
		if ret.rec and param.parameter then -- PM: 2017-06-08, add ret.rec to parameters, do not override previous parameters
			param.parameter = util.tableCombine(ret.rec, param.parameter, "no-error")
		end

		if prf.data_query ~= nil then
			ret.data = ret.data or {}
			if type(prf.data_query) ~= "table" then
				return {error = l("error in query '%s', tag 'data_query' is not an array", tostring(prf.name))}
			else
				for _, rec in ipairs(prf.data_query) do
					if rec.run then
						if type(rec.run) ~= "table" then
							return {error = l("error in query '%s', tag 'data_query' array object 'run' is not a table", tostring(prf.name))}
						end
						-- dialog/productivity_report/query.json
						-- {"run": [["parameter.production_lot", "=", ["util.distinctKeyArray", ["wpa.data", "production_lot"]]]]},
						-- AGA, execute.runCode -> jsonStatementType(), palauttaa "array" jota runStatement() ei hanskaa ollenkaan
						-- miksi ei tule mitään vikailmoitusta vaikka koodi ei toimi?
						-- onko pakko olla array arrayta?
						-- miksi ei tule mitään vikailmoitusta jos koodissa ei ole array arrayta vaan pelkkä array?
						local _, err = execute.runCode(rec.run, {data = ret.data, parameter = param.parameter})
						if err then
							return {error = l("error in in query '%s', calling code '%s': '%s'", tostring(prf.name), tostring(json.toJson(ret.rec.run)), err)}
						end
					elseif type(rec.tag) ~= "string" then
						return {error = l("error in query '%s', tag 'data_query' array object does not contain 'tag'", tostring(prf.name))}
					end
					if rec.query then
					-- data contains query-tag and field-tag (json is already expanded)
					-- todo: this should handle also possible columns tag
						local parameter = util.clone(param.parameter) or {}
						if rec.columns then
							parameter.columns = rec.columns -- util.prf(rec.columns).columns
						end
						local ans, err = queryJson(rec.query, parameter)
						if err or ans.error then
							return {error = l("error in query '%s', data subquery '%s':\n%s'", tostring(prf.name), tostring(rec.query), tostring(err or ans.error))}
						end
						ret.data[rec.tag] = ans -- fix: why ans.data = {} does not turn to "[]" in json?
					end
				end
			end
		end

		if ret.rec ~= nil then
			if ret.rec.error then
				return {error = ret.rec.error} --.."\nrec: "..tostring(prf.rec)}
			end

			-- set parameter values to rec
			for key in pairs(ret.rec) do
				if type(ret.rec[key]) == "string" and peg.found(ret.rec[key], "parameter.") then
					ret.rec[key] = execute.getTagValue(ret.rec[key], ret.rec)
				end
			end

			if ret.rec.run then
				local _, err = execute.runCode(ret.rec.run, ret.rec)
				if err then
					return {error = l("error in calling code '%s':  '%s'", tostring(json.toJson(ret.rec.run)), err)}
				end
			end

			if type(ret.rec["return"]) == "table" then
				for key, val in pairs(ret.rec["return"]) do
					if type(val) == "string" and peg.endsWith(val, ".json") then
						local prf, err = queryPreference(val)
						if prf and not err then
							ret.rec[key] = prf
						end
					end
				end
			end

			if ret.rec.query and #ret.rec.query > 0 then
				local function addRetRecQuery(jsonName)
					local qryRet, err = queryJson(jsonName, ret.rec)
					if err and not ret.error then
						-- ret.error = err
						-- return
					end
					if qryRet and qryRet.data and qryRet.data[1] and qryRet.error == nil then
						ret.rec = util.tableCombine(ret.rec, qryRet.data[1], "no-error")
					end
				end
				if type(ret.rec.query) == "table" then
					for _, jsonName in ipairs(ret.rec.query) do
						addRetRecQuery(jsonName)
					end
				else
					addRetRecQuery(ret.rec.query)
				end
				if ret.error then
					-- return {error = ret.error} --.."\nrec: "..tostring(prf.rec)}
				end
			end

			if ret.rec.__load_json then
				for key, val in pairs(ret.rec.__load_json) do
					local jsonPrf = queryPreference(val)
					if jsonPrf.error then
						return {error = jsonPrf.error}
					end
					ret.rec[key] = json.toJson(jsonPrf)
				end
				ret.rec.__load_json = nil
			end
		end
		if ret.popup == nil and prf.popup ~= nil then
			ret.popup = prf.popup
		end
		if ret.popup ~= nil then
			if ret.popup.error then
				return {error = ret.popup.error} --.."\npopup: "..tostring(prf.popup)}
			else
				-- popup can contain query and it's parameter
				for key, rec in pairs(ret.popup) do
					if type(rec) == "table" and rec.query then
						local content = queryJson(rec.query, rec.parameter)
						if type(content.data) ~= "table" then
							-- util.printWarning(l("popup is nil, query '%s', parameter '%s'", tostring(rec.query), tostring(rec.parameter)))
						else
							local popup = {}
							for i, rec2 in ipairs(content.data) do
								local show -- show tag can be text or array: ["fld1", " - ", "fld2"]
								if type(rec.show) == "table" then
									show = {}
									for j = 1, #rec.show, 2 do
										show[j] = rec2[rec.show[j]]
										if j + 1 <= #rec.show then
											show[j + 1] = rec.show[j + 1] -- add divider
										end
									end
									show = table.concat(show)
								else
									show = rec2[rec.show]
								end
								local pop = {show = show}
								for key, val in pairs(rec) do
									if key ~= "query" and key ~= "show" then
										pop[key] = rec2[val]
									end
								end
								popup[i] = pop
							end
							ret.popup[key] = popup
						end
					end
				end
			end
		end
		if ret.grid == nil and prf.grid ~= nil then
			ret.grid = prf.grid
		end
		if ret.grid ~= nil then
			local queryGridParam
			if param.parameter and ret.rec then
				-- param.parameter overrides keys in ret.rec, no error reporting
				queryGridParam = util.tableCombine(ret.rec, param.parameter, "no-error")
			elseif param.parameter then
				queryGridParam = param.parameter
			elseif ret.rec then
				queryGridParam = ret.rec
			end
			ret.grid = queryGrid(ret.grid, queryGridParam)
			if ret.grid.error then
				return {error = ret.grid.error} -- .."\ngrid: "..tostring(prf.grid)}
			end
		end
	end
	if ret.grid then -- add missing data array
		for _, rec in pairs(ret.grid) do
			if not rec.data then
				rec.data = {}
			end
		end
	end
	return ret
end

local function deleteJson(query, parameter)
	local err
	if type(query) == "string" then
		query, err = util.prf("query/"..query)
	end
	if not query then
		return err
	end
	local connDatabase, conn
	if parameter and parameter.conn then
		conn = parameter.conn
	else
		conn, connDatabase = db.jsonConnection(conn, query)
	end
	 -- or (parameter and parameter.connection) or (query.parameter and query.parameter.connection)
	local ret = db.queryJson(conn, query, parameter, nil, {only_query = true})
	local tbl
	if query.table then
		tbl = query.table
	elseif query.field and #query.field > 0 then
		tbl = db.fieldNameToTableNumber(query.field[1])
	else
		local err = l("preference '%s' contains no table or field -tag", tostring(query))
		util.printError(err)
		return err
	end
	if tbl then
		local err = db.deleteSelection(conn, tbl)
		if err then
			return err
		end
	end
	if connDatabase then
		db.disconnect(conn)
	end
	--end
end

local function changeName(table, queryName)
	local prfTbl, err = util.prf("query/generate/query_name.json")
	if not err then
		if type(prfTbl[table]) == "table" then
			for newName,oldName in pairs(prfTbl[table]) do
				if oldName == queryName then
					newName = peg.replace(newName,".json", "")..".json"
					return table.."/"..newName
				end
			end
		end
	end
	return queryName
end

return {
	init = init,
	-- saveStructure = saveStructure,
	-- getSessionParameter = getSessionParameter,
	-- save = save,
	queryJsonName = queryJsonName,
	queryJson = queryJson,
	queryRec = queryRec,
	queryJsonData = queryJsonData,
	querySql = querySql,
	query = query,
	queryRecord = queryRecord,
	deleteJson = deleteJson,
	changeName = changeName,
}
