使用erlang odbc查询时是否有人遇到此错误:
{:error,:process_not_owner_of_odbc_connection}
我正在编写一个连接池,并且:ODBC.connect('conn string)在genserver中运行,返回的pid进入状态...但是当我从生成器服务器中取出PID时,尝试运行带有该pid的odbc.param_query时出现上述错误...如果我们可以使用在genserver中创建的pid,我们如何设置创建连接池?
有人有什么想法吗?
GenServer:
black
调用功能:
defmodule ItemonboardingApi.ConnectionPoolWorker do
use GenServer
def start_link([]) do
IO.puts "Starting Connection Pool"
GenServer.start_link(__MODULE__, nil, [])
end
def init(_) do
:odbc.start
{ok, pid} = :odbc.connect('DSN=;UID=;PWD=', [])
IO.inspect pid
{:ok, pid}
end
def handle_call(:get_connection, _from, state) do
IO.puts "Inspecting State:"
IO.inspect state
IO.puts("process #{inspect(self())} getting odbc connection")
{:reply, state, state}
end
end
我已经确认genserver中的pids会感染正确的odbc pids而GenServer.Call会返回其中一个。
**** **** EDIT 这是我为解决这个问题所做的工作。我不知道创建连接的进程必须是运行查询的进程。我的工作人员稍微改变一下,将查询传递给了我的问题。这是一个粗略的第一步,仍然需要对工人做一些事情。
def get_standards_like(standard) do
:poolboy.transaction(
:connection_pool,
fn pid ->
connection = GenServer.call(pid, :get_connection)
IO.inspect connection
val =
String.upcase(standard)
|> to_char_list
# Call Stored Proc Statement
spstmt = '{call invlibr.usp_vm_getStandards (?)}'
case :odbc.param_query(connection, spstmt, [
{{:sql_char, 50}, [val]}
])
|> map_to_type(ItemonboardingCore.Standard)
do
{:ok, mapped} ->
{:ok, mapped}
{:updated, affected_count} ->
{:ok, affected_count}
{:executed, o, a} ->
{:ok, o, a}
{:error, _} ->
{:bad}
end
end
)
end
答案 0 :(得分:3)
这会成为一个问题,就像凯文指出的那样,你无法为odbc和其他驱动程序(如mysql / otp)转移连接所有权。
如果您想使用连接池,请改为https://github.com/mysql-otp/mysql-otp-poolboy
否则,您可以使用任何池,但执行sql查询的进程必须是打开连接的进程。
在Erlang中的sql_query_priv(Conn, Conn_Params, {SQL, Params}) ->
lager:debug("~p:sql_query_priv trying to execute query: ~p, with params: ~p, conn = ~p~n", [?MODULE, SQL, Params, Conn]),
case Conn of
null -> try mysql:start_link(Conn_Params) of
{ok, NewConn} ->
lager:info("~p:sql_query_priv Connection to DB Restored", [?MODULE]),
try mysql:query(NewConn, SQL, Params) of
ok -> {ok, NewConn, []};
{ok, _Columns, Results} -> {ok, NewConn, Results};
{error, Reason} ->
lager:error("~p:sql_query_priv Connection To DB Failed, Reason: ~p~n", [?MODULE, {error, Reason}]),
exit(NewConn, normal),
{error, null, Reason}
catch
Exception:Reason ->
lager:error("~p:sql_query_priv Connection To DB Failed, Exception:~p Reason: ~p~n", [?MODULE, Exception, Reason]),
{error, null, {Exception, Reason}}
end;
{error, Reason} ->
lager:error("~p:sql_query_priv Connection To DB Failed, Reason: ~p~n", [?MODULE, {error, Reason}]),
{error, Conn, Reason}
catch
Exception:Reason ->
lager:error("~p:sql_query_priv Connection To DB Failed, Exception:~p Reason: ~p~n", [?MODULE, Exception, Reason]),
{error, Conn, {Exception, Reason}}
end;
Conn -> try mysql:query(Conn, SQL, Params) of
ok -> {ok, Conn, []};
{ok, _Columns, Results} -> {ok, Conn, Results};
{error, Reason} ->
try exit(Conn, normal) of
_Any -> ok
catch
_E:_R -> ok
end,
lager:error("~p:sql_query_priv Connection To DB Failed, Reason: ~p~n", [?MODULE, {error, Reason}]),
{error, null, Reason}
catch
Exception:Reason ->
try exit(Conn, normal) of
_Any -> ok
catch
_E:_R -> ok
end,
lager:error("~p:sql_query_priv Connection To DB Failed, Exception:~p Reason: ~p~n", [?MODULE, Exception, Reason]),
{error, null, {Exception, Reason}}
end
end.
答案 1 :(得分:2)
根据relevant documentation,odbc
连接对创建连接的Genserver
进程是私有的。
打开与数据库的连接。该连接与 创建它的过程,只能通过它访问。这个 函数可能会生成新的进程来处理连接。这些 如果创建连接的进程将终止进程 死亡或如果你打电话给disconnect / 1。
您可以将其与可以设置为ETS
的{{1}}表进行比较,但在private
表的情况下,您可以将它们设为ETS
。对于public
个关联,这是不可能的,因此您应该将代码移到odbc