11defmodule Tds do
2+ @ moduledoc """
3+ Microsoft SQL Server driver for Elixir.
4+
5+ Tds is partial implementation of the Micorosoft SQL Server
6+ [MS-TDS](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds)
7+ Tabular Data Stream Protocol.
8+
9+ A Tds query is performed in separate server-side prepare and execute stages.
10+ At the moment query handle is not reused, but there is plan to cahce handles in
11+ near feature. It uses [RPC](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/619c43b6-9495-4a58-9e49-a4950db245b3)
12+ requests by default to `Sp_Prepare` (ProcId=11) and `Sp_Execute` (ProcId=12)
13+ query, but it is possible to configure driver to use only Sp_ExecuteSql.
14+ Please consult with [configuration](readme.html#configuration) how to do this.
15+ """
216 alias Tds.Query
317
418 @ timeout 5000
519 @ execution_mode :prepare_execute
620
21+ @ type start_option ::
22+ { :hostname , String . t ( ) }
23+ | { :port , :inet . port_number ( ) }
24+ | { :database , String . t ( ) }
25+ | { :username , String . t ( ) }
26+ | { :password , String . t ( ) }
27+ | { :timeout , timeout }
28+ | { :connect_timeout , timeout }
29+ | DBConnection . start_option ( )
30+
31+ @ type isolation_level ::
32+ :read_uncommitted
33+ | :read_committed
34+ | :repeatable_read
35+ | :serializable
36+ | :snapshot
37+ | :no_change
38+
39+ @ type conn :: DBConnection . conn ( )
40+
41+ @ type resultset :: list ( Tds.Result . t ( ) )
42+
43+ @ type option :: DBConnection . option ( )
44+
45+ @ type transaction_option ::
46+ { :mode , :transaction | :savepoint }
47+ | { :isolation_level , isolation_level ( ) }
48+ | option ( )
49+
50+ @ type execute_option ::
51+ { :decode_mapper , ( list -> term ) }
52+ | { :resultset , boolean ( ) }
53+ | option
54+
55+ @ spec start_link ( [ start_option ] ) ::
56+ { :ok , conn } | { :error , Tds.Error . t ( ) | term }
757 def start_link ( opts \\ [ ] ) do
858 DBConnection . start_link ( Tds.Protocol , default ( opts ) )
959 end
1060
11- def query ( pid , statement , params , opts \\ [ ] ) do
61+ @ spec query ( conn , iodata , list , [ execute_option ] ) ::
62+ { :ok , Tds.Result . t ( ) } | { :error , Exception . t ( ) }
63+ def query ( conn , statement , params , opts \\ [ ] ) do
1264 query = % Query { statement: statement }
1365 opts = Keyword . put_new ( opts , :parameters , params )
1466
15- case DBConnection . prepare_execute ( pid , query , params , opts ) do
67+ case DBConnection . prepare_execute ( conn , query , params , opts ) do
1668 { :ok , _query , result } -> { :ok , result }
1769 { :error , err } -> { :error , err }
1870 end
1971 end
2072
21- def query! ( pid , statement , params , opts \\ [ ] ) do
73+ @ spec query! ( conn , iodata , list , [ execute_option ] ) ::
74+ Tds.Result . t ( ) | no_return ( )
75+ def query! ( conn , statement , params , opts \\ [ ] ) do
2276 query = % Query { statement: statement }
2377 opts = Keyword . put_new ( opts , :parameters , params )
2478
25- case DBConnection . prepare_execute ( pid , query , params , opts ) do
79+ case DBConnection . prepare_execute ( conn , query , params , opts ) do
2680 { :ok , _query , result } -> result
2781 { :error , % { mssql: % { msg_text: msg } } } -> raise Tds.Error , msg
2882 { :error , err } -> raise err
@@ -33,76 +87,93 @@ defmodule Tds do
3387 Executes statement that can contain multiple sql batches, result will contain
3488 all results that server yield for each batch.
3589 """
36- def query_multi ( pid , statemnt , params , opts \\ [ ] ) do
90+ @ spec query_multi ( conn ( ) , iodata ( ) , option ( ) , [ execute_option ] ) ::
91+ { :ok , resultset ( ) }
92+ | { :error , Exception . t ( ) }
93+ def query_multi ( conn , statemnt , params , opts \\ [ ] ) do
3794 query = % Query { statement: statemnt }
3895
3996 opts =
4097 opts
4198 |> Keyword . put_new ( :parameters , params )
4299 |> Keyword . put_new ( :resultset , true )
43100
44- case DBConnection . prepare_execute ( pid , query , params , opts ) do
101+ case DBConnection . prepare_execute ( conn , query , params , opts ) do
45102 { :ok , _query , resultset } -> { :ok , resultset }
46103 { :error , err } -> { :error , err }
47104 end
48105 end
49106
50- def prepare ( pid , statement , opts \\ [ ] ) do
107+ @ spec prepare ( conn , iodata , [ option ] ) ::
108+ { :ok , Tds.Query . t ( ) } | { :error , Exception . t ( ) }
109+ def prepare ( conn , statement , opts \\ [ ] ) do
51110 query = % Query { statement: statement }
52111
53- case DBConnection . prepare ( pid , query , opts ) do
112+ case DBConnection . prepare ( conn , query , opts ) do
54113 { :ok , query } -> { :ok , query }
55114 { :error , err } -> { :error , err }
56115 end
57116 end
58117
59- def prepare! ( pid , statement , opts \\ [ ] ) do
118+ @ spec prepare! ( conn , iodata , [ option ] ) :: Tds.Query . t ( ) | no_return ( )
119+ def prepare! ( conn , statement , opts \\ [ ] ) do
60120 query = % Query { statement: statement }
61121
62- case DBConnection . prepare ( pid , query , opts ) do
122+ case DBConnection . prepare ( conn , query , opts ) do
63123 { :ok , query } -> query
64124 { :error , % { mssql: % { msg_text: msg } } } -> raise Tds.Error , msg
65125 { :error , err } -> raise err
66126 end
67127 end
68128
69- def execute ( pid , query , params , opts \\ [ ] ) do
70- case DBConnection . execute ( pid , query , params , opts ) do
129+ @ spec execute ( conn , Tds.Query . t ( ) , list , [ execute_option ] ) ::
130+ { :ok , Tds.Query . t ( ) , Tds.Result . t ( ) }
131+ | { :error , Tds.Error . t ( ) }
132+ def execute ( conn , query , params , opts \\ [ ] ) do
133+ case DBConnection . execute ( conn , query , params , opts ) do
71134 { :ok , q , result } -> { :ok , q , result }
72135 { :error , err } -> { :error , err }
73136 end
74137 end
75138
76- def execute! ( pid , query , params , opts \\ [ ] ) do
77- case DBConnection . execute ( pid , query , params , opts ) do
139+ @ spec execute! ( conn , Tds.Query . t ( ) , list , [ execute_option ] ) ::
140+ Tds.Result . t ( )
141+ def execute! ( conn , query , params , opts \\ [ ] ) do
142+ case DBConnection . execute ( conn , query , params , opts ) do
78143 { :ok , _q , result } -> result
79144 { :error , % { mssql: % { msg_text: msg } } } -> raise Tds.Error , msg
80145 { :error , err } -> raise err
81146 end
82147 end
83148
84- def close ( pid , query , opts \\ [ ] ) do
85- case DBConnection . close ( pid , query , opts ) do
149+ @ spec close ( conn , Tds.Query . t ( ) , [ option ] ) :: :ok | { :error , Exception . t ( ) }
150+ def close ( conn , query , opts \\ [ ] ) do
151+ case DBConnection . close ( conn , query , opts ) do
86152 { :ok , result } -> { :ok , result }
87153 { :error , err } -> { :error , err }
88154 end
89155 end
90156
91- def close! ( pid , query , opts \\ [ ] ) do
92- case DBConnection . close ( pid , query , opts ) do
157+ @ spec close! ( conn , Tds.Query . t ( ) , [ option ] ) :: :ok
158+ def close! ( conn , query , opts \\ [ ] ) do
159+ case DBConnection . close ( conn , query , opts ) do
93160 { :ok , result } -> result
94161 { :error , % { mssql: % { msg_text: msg } } } -> raise Tds.Error , msg
95162 { :error , err } -> raise err
96163 end
97164 end
98165
99- def transaction ( pid , fun , opts \\ [ ] ) do
100- DBConnection . transaction ( pid , fun , opts )
166+ @ spec transaction ( conn , ( DBConnection . t ( ) -> result ) , [ transaction_option ( ) ] ) ::
167+ { :ok , result } | { :error , any }
168+ when result: var
169+ def transaction ( conn , fun , opts \\ [ ] ) do
170+ DBConnection . transaction ( conn , fun , opts )
101171 end
102172
103173 @ spec rollback ( DBConnection . t ( ) , reason :: any ) :: no_return
104174 defdelegate rollback ( conn , any ) , to: DBConnection
105175
176+ @ spec child_spec ( [ start_option ] ) :: Supervisor.Spec . spec ( )
106177 def child_spec ( opts ) do
107178 DBConnection . child_spec ( Tds.Protocol , default ( opts ) )
108179 end
0 commit comments