odbc.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 911 行 · 第 1/3 页
ERL
911 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%-module(odbc).-behaviour(gen_server).-include("odbc_internal.hrl").%% API ---------------------------------------------------------------------export([connect/2, disconnect/1, commit/2, commit/3, sql_query/2, sql_query/3, select_count/2, select_count/3, first/1, first/2, last/1, last/2, next/1, next/2, prev/1, prev/2, select/3, select/4, param_query/3, param_query/4, describe_table/2, describe_table/3]).%%-------------------------------------------------------------------------%% supervisor callbacks-export([start_link_sup/1]).%% gen_server callbacks-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).%%--------------------------------------------------------------------------%% Internal state-record(state, {erlang_port, % The port to the c-program reply_to, % gen_server From parameter owner, % Pid of the connection owner result_set = undefined, % exists | undefined auto_commit_mode = on, % on | off %% Indicates if first, last and "select absolut" %% is supported by the odbc driver. absolute_pos, % true | false %% Indicates if prev and "select relative" %% is supported by the odbc driver. relative_pos, % true | false scrollable_cursors, % on | off %% connecting | connected | disconnecting state = connecting, %% For timeout handling pending_request, num_timeouts = 0, listen_sockets, sup_socket, odbc_socket }).%%--------------------------------------------------------------------------%%%=========================================================================%%% API%%%=========================================================================%%-------------------------------------------------------------------------%% connect(ConnectionStr, Options) -> {ok, ConnectionReferense} |%% {error, Reason}%% Description: Spawns an erlang control process that will open a port%% to a c-process that uses the ODBC API to open a connection%% to the database. %%-------------------------------------------------------------------------connect(ConnectionStr, Options) when list(ConnectionStr), list(Options) -> %% Start of the odbc application should really be handled by the %% application using odbc. case application:start(odbc) of {error,{already_started,odbc}} -> ok; ok -> error_logger:info_report("The odbc application was not started." " Has now been started as a temporary" " application.") end, %% Spawn the erlang control process. case supervisor:start_child(odbc_sup, [[{client, self()}]]) of {ok, Pid} -> connect(Pid, ConnectionStr, Options); {error, Reason} -> {error, Reason} end.%%--------------------------------------------------------------------------%% disconnect(ConnectionReferense) -> ok | {error, Reason}%% %% Description: Disconnects from the database and terminates both the erlang%% control process and the database handling c-process. %%--------------------------------------------------------------------------disconnect(ConnectionReference) when pid(ConnectionReference)-> ODBCCmd = [?CLOSE_CONNECTION], case call(ConnectionReference, {disconnect, ODBCCmd}, 5000) of {error, connection_closed} -> %% If the connection has already been closed the effect of %% disconnect has already been acomplished ok; %% Note a time out of this call will return ok, as disconnect %% will always succeed, the time out is to make sure %% the connection is killed brutaly if it will not be shut down %% gracefully. ok -> ok; %% However you may receive an error message as result if you try to %% disconnect a connection started by another process. Other -> Other end. %%--------------------------------------------------------------------------%% commit(ConnectionReference, CommitMode, <TimeOut>) -> ok | {error,Reason}%% %% Description: Commits or rollbacks a transaction. Needed on connections%% where automatic commit is turned off. %%--------------------------------------------------------------------------commit(ConnectionReference, CommitMode) -> commit(ConnectionReference, CommitMode, ?DEFAULT_TIMEOUT).commit(ConnectionReference, commit, infinity) when pid(ConnectionReference) -> ODBCCmd = [?COMMIT_TRANSACTION, ?COMMIT], call(ConnectionReference, {commit, ODBCCmd}, infinity);commit(ConnectionReference, commit, TimeOut) when pid(ConnectionReference), integer(TimeOut), TimeOut > 0 -> ODBCCmd = [?COMMIT_TRANSACTION, ?COMMIT], call(ConnectionReference, {commit, ODBCCmd}, TimeOut);commit(ConnectionReference, rollback, infinity) when pid(ConnectionReference) -> ODBCCmd = [?COMMIT_TRANSACTION, ?ROLLBACK], call(ConnectionReference, {commit, ODBCCmd}, infinity);commit(ConnectionReference, rollback, TimeOut) when pid(ConnectionReference), integer(TimeOut), TimeOut > 0 -> ODBCCmd = [?COMMIT_TRANSACTION, ?ROLLBACK], call(ConnectionReference, {commit, ODBCCmd}, TimeOut).%%--------------------------------------------------------------------------%% sql_query(ConnectionReference, SQLQuery, <TimeOut>) -> {updated, NRows} |%% {selected, ColNames, Rows} | {error, Reason} %% %% Description: Executes a SQL query. If it is a SELECT query the%% result set is returned, otherwise the number of affected %% rows are returned.%%--------------------------------------------------------------------------sql_query(ConnectionReference, SQLQuery) -> sql_query(ConnectionReference, SQLQuery, ?DEFAULT_TIMEOUT).sql_query(ConnectionReference, SQLQuery, infinity) when pid(ConnectionReference), list(SQLQuery) -> ODBCCmd = [?QUERY, SQLQuery], call(ConnectionReference, {sql_query, ODBCCmd}, infinity);sql_query(ConnectionReference, SQLQuery, TimeOut) when pid(ConnectionReference),list(SQLQuery),integer(TimeOut),TimeOut>0 -> ODBCCmd = [?QUERY, SQLQuery], call(ConnectionReference, {sql_query, ODBCCmd}, TimeOut).%%--------------------------------------------------------------------------%% select_count(ConnectionReference, SQLQuery, <TimeOut>) -> {ok, NrRows} |%% {error, Reason} %% %% Description: Executes a SQL SELECT query and associates the result set%% with the connection. A cursor is positioned before%% the first row in the result set and the number of%% rows in the result set is returned.%%--------------------------------------------------------------------------select_count(ConnectionReference, SQLQuery) -> select_count(ConnectionReference, SQLQuery, ?DEFAULT_TIMEOUT).select_count(ConnectionReference, SQLQuery, infinity) when pid(ConnectionReference), list(SQLQuery) -> ODBCCmd = [?SELECT_COUNT, SQLQuery], call(ConnectionReference, {select_count, ODBCCmd}, infinity);select_count(ConnectionReference, SQLQuery, TimeOut) when pid(ConnectionReference), list(SQLQuery), integer(TimeOut), TimeOut > 0 -> ODBCCmd = [?SELECT_COUNT, SQLQuery], call(ConnectionReference, {select_count, ODBCCmd}, TimeOut).%%--------------------------------------------------------------------------%% first(ConnectionReference, <TimeOut>) -> {selected, ColNames, Rows} | %% {error, Reason} %% %% Description: Selects the first row in the current result set. The cursor%% : is positioned at this row. %%--------------------------------------------------------------------------first(ConnectionReference) -> first(ConnectionReference, ?DEFAULT_TIMEOUT). first(ConnectionReference, infinity) when pid(ConnectionReference) -> ODBCCmd = [?SELECT, ?SELECT_FIRST], call(ConnectionReference, {select_cmd, absolute, ODBCCmd}, infinity);first(ConnectionReference, TimeOut) when pid(ConnectionReference), integer(TimeOut), TimeOut > 0 -> ODBCCmd = [?SELECT, ?SELECT_FIRST], call(ConnectionReference, {select_cmd, absolute, ODBCCmd}, TimeOut).%%--------------------------------------------------------------------------%% last(ConnectionReference, <TimeOut>) -> {selected, ColNames, Rows} | %% {error, Reason} %% %% Description: Selects the last row in the current result set. The cursor%% : is positioned at this row. %%--------------------------------------------------------------------------last(ConnectionReference) -> last(ConnectionReference, ?DEFAULT_TIMEOUT). last(ConnectionReference, infinity) when pid(ConnectionReference) -> ODBCCmd = [?SELECT, ?SELECT_LAST], call(ConnectionReference, {select_cmd, absolute, ODBCCmd}, infinity);last(ConnectionReference, TimeOut) when pid(ConnectionReference), integer(TimeOut), TimeOut > 0 -> ODBCCmd = [?SELECT, ?SELECT_LAST], call(ConnectionReference, {select_cmd, absolute, ODBCCmd}, TimeOut).%%--------------------------------------------------------------------------%% next(ConnectionReference, <TimeOut>) -> {selected, ColNames, Rows} | %% {error, Reason} %% %% Description: Selects the next row relative the current cursor position %% : in the current result set. The cursor is positioned at %% : this row. %%--------------------------------------------------------------------------next(ConnectionReference) -> next(ConnectionReference, ?DEFAULT_TIMEOUT). next(ConnectionReference, infinity) when pid(ConnectionReference) -> ODBCCmd = [?SELECT, ?SELECT_NEXT], call(ConnectionReference, {select_cmd, next, ODBCCmd}, infinity);next(ConnectionReference, TimeOut) when pid(ConnectionReference), integer(TimeOut), TimeOut > 0 -> ODBCCmd = [?SELECT, ?SELECT_NEXT], call(ConnectionReference, {select_cmd, next, ODBCCmd}, TimeOut).%%--------------------------------------------------------------------------%% prev(ConnectionReference, <TimeOut>) -> {selected, ColNames, Rows} | %% {error, Reason} %% %% Description: Selects the previous row relative the current cursor %% : position in the current result set. The cursor is%% : positioned at this row. %%--------------------------------------------------------------------------prev(ConnectionReference) -> prev(ConnectionReference, ?DEFAULT_TIMEOUT). prev(ConnectionReference, infinity) when pid(ConnectionReference) -> ODBCCmd = [?SELECT, ?SELECT_PREV], call(ConnectionReference, {select_cmd, relative, ODBCCmd}, infinity);prev(ConnectionReference, TimeOut) when pid(ConnectionReference), integer(TimeOut), TimeOut > 0 -> ODBCCmd = [?SELECT, ?SELECT_PREV], call(ConnectionReference, {select_cmd, relative, ODBCCmd}, TimeOut).%%--------------------------------------------------------------------------%% select(ConnectionReference, <Timeout>) -> {selected, ColNames, Rows} | %% {error, Reason} %% %% Description: Selects <N> rows. If <Position> is next it is%% semanticly eqvivivalent of calling next/[1,2] <N>%% times. If <Position> is {relative, Pos} <Pos> will be%% used as an offset from the current cursor position to%% determine the first selected row. If <Position> is%% {absolute, Pos}, <Pos> will be the number of the first%% row selected. After this function has returned the%% cursor is positioned at the last selected row.%%--------------------------------------------------------------------------select(ConnectionReference, Position, N) -> select(ConnectionReference, Position, N, ?DEFAULT_TIMEOUT).select(ConnectionReference, next, N, infinity) when pid(ConnectionReference), integer(N), N > 0 -> ODBCCmd = [?SELECT, ?SELECT_N_NEXT, integer_to_list(?DUMMY_OFFSET), ";", integer_to_list(N), ";"], call(ConnectionReference, {select_cmd, next, ODBCCmd}, infinity);select(ConnectionReference, next, N, TimeOut) when pid(ConnectionReference), integer(N), N > 0, integer(TimeOut), TimeOut > 0 -> ODBCCmd = [?SELECT, ?SELECT_N_NEXT, integer_to_list(?DUMMY_OFFSET), ";", integer_to_list(N), ";"], call(ConnectionReference, {select_cmd, next, ODBCCmd}, TimeOut);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?