1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22
23-module(postgres).
24
25%% Note: This directive should only be used in test suites.
26-compile(export_all).
27
28%-------------------------------------------------------------------------
29connection_string() ->
30    case test_server:os_type() of
31	{unix, sunos} ->
32	    "DSN=Postgres;UID=odbctest";
33	{unix, linux} ->
34	    Size = erlang:system_info({wordsize, external}),
35	    linux_dist_connection_string(Size)
36    end.
37
38linux_dist_connection_string(4) ->
39    case linux_dist() of
40	"ubuntu" ->
41	    "DSN=PostgresLinuxUbuntu;UID=odbctest";
42	_ ->
43	    "DSN=PostgresLinux;UID=odbctest"
44    end;
45
46linux_dist_connection_string(_) ->
47    case linux_dist() of
48	"ubuntu" ->
49	    "DSN=PostgresLinux64Ubuntu;UID=odbctest";
50	_ ->
51	    "DSN=PostgresLinux64;UID=odbctest"
52    end.
53
54linux_dist() ->
55    case file:read_file("/etc/issue") of
56	{ok, Binary} ->
57	    [Dist | _ ] = string:tokens(binary_to_list(Binary), " "),
58	    string:to_lower(Dist);
59	{error, _} ->
60	    other
61    end.
62
63
64%-------------------------------------------------------------------------
65insert_result() ->
66    {selected,["id","data"],[{1,"bar"}]}.
67
68update_result() ->
69    {selected,["id","data"],[{1,"foo"}]}.
70
71selected_ID(N, next) ->
72    {selected,["id"],[{N}]};
73
74selected_ID(_, _) ->
75    {error, driver_does_not_support_function}.
76
77selected_next_N(1)->
78    {selected,["id"],
79     [{1},
80      {2},
81      {3}]};
82
83selected_next_N(2)->
84    {selected,["id"],
85     [{4},
86      {5}]}.
87
88selected_relative_N(_)->
89    {error, driver_does_not_support_function}.
90
91selected_absolute_N(_)->
92    {error, driver_does_not_support_function}.
93
94selected_list_rows() ->
95    {selected,["id", "data"],[[1, "bar"],[2,"foo"]]}.
96
97first_list_rows() ->
98    {error, driver_does_not_support_function}.
99last_list_rows() ->
100    {error, driver_does_not_support_function}.
101prev_list_rows() ->
102    {error, driver_does_not_support_function}.
103next_list_rows() ->
104    {selected,["id","data"],[[1,"bar"]]}.
105
106%% In case we get a better postgres driver that support this some day .....
107multiple_select()->
108    [{selected,["id", "data"],[{1, "bar"},{2, "foo"}]},
109     {selected,["id"],[{"foo"}]}].
110
111multiple_mix()->
112    [{updated, 1},{updated, 1},
113     {selected,["id", "data"],[{1, "foobar"},{2, "foo"}]},
114     {updated, 1}, {selected,["data"],[{"foo"}]}].
115
116%-------------------------------------------------------------------------
117fixed_char_min() ->
118    1.
119fixed_char_max() ->
120    2000.
121
122create_fixed_char_table(Size) ->
123    " (FIELD char(" ++ integer_to_list(Size) ++ "))".
124
125%-------------------------------------------------------------------------
126var_char_min() ->
127    1.
128var_char_max() ->
129    2000.
130
131create_var_char_table(Size) ->
132    " (FIELD varchar(" ++ integer_to_list(Size) ++ "))".
133
134%-------------------------------------------------------------------------
135text_min() ->
136    1.
137text_max() ->
138   2147483646. % 2147483647. %% 2^31 - 1
139
140create_text_table() ->
141    " (FIELD text)".
142
143%-------------------------------------------------------------------------
144create_timestamp_table() ->
145    " (FIELD TIMESTAMP)".
146
147%-------------------------------------------------------------------------
148small_int_min() ->
149    -32768.
150small_int_max() ->
151    32767.
152
153create_small_int_table() ->
154     " (FIELD smallint)".
155
156small_int_min_selected() ->
157    {selected,["field"],[{-32768}]}.
158
159small_int_max_selected() ->
160    {selected,["field"], [{32767}]}.
161
162%-------------------------------------------------------------------------
163int_min() ->
164   -2147483648.
165int_max() ->
166    2147483647.
167
168create_int_table() ->
169     " (FIELD int)".
170
171int_min_selected() ->
172    {selected,["field"],[{-2147483648}]}.
173
174int_max_selected() ->
175    {selected,["field"], [{2147483647}]}.
176
177%-------------------------------------------------------------------------
178big_int_min() ->
179    -9223372036854775808.
180
181big_int_max() ->
182    9223372036854775807.
183
184create_big_int_table() ->
185     " (FIELD bigint )".
186
187big_int_min_selected() ->
188    {selected,["field"], [{"-9223372036854775808"}]}.
189
190big_int_max_selected() ->
191    {selected,["field"], [{"9223372036854775807"}]}.
192
193%-------------------------------------------------------------------------
194bit_false() ->
195    0.
196bit_true() ->
197    1.
198
199create_bit_table() ->
200     " (FIELD bit)".
201
202bit_false_selected() ->
203    {selected,["field"],[{"0"}]}.
204
205bit_true_selected() ->
206    {selected,["field"], [{"1"}]}.
207
208%-------------------------------------------------------------------------
209float_min() ->
210    5.0e-324.
211float_max() ->
212    1.79e+308.
213
214create_float_table() ->
215    " (FIELD float)".
216
217float_underflow() ->
218    "2.4e-324".
219float_overflow() ->
220    "1.80e+308".
221
222float_zero_selected() ->
223    {selected,["field"],[{0.00000e+0}]}.
224
225%-------------------------------------------------------------------------
226real_min() ->
227    -3.40e+38.
228real_max() ->
229    3.40e+38.
230
231real_underflow() ->
232    "-3.41e+38".
233
234real_overflow() ->
235    "3.41e+38".
236
237create_real_table() ->
238    " (FIELD real)".
239
240real_zero_selected() ->
241    {selected,["field"],[{0.00000e+0}]}.
242
243%-------------------------------------------------------------------------
244param_select_small_int() ->
245    {selected,["field"],[{1}, {2}]}.
246
247param_select_int() ->
248    Int = small_int_max() + 1,
249    {selected,["field"],[{1}, {Int}]}.
250
251param_select_decimal() ->
252    {selected,["field"],[{1},{2}]}.
253
254param_select_numeric() ->
255    {selected,["field"],[{1},{2}]}.
256
257param_select_float() ->
258    {selected,["field"],[{1.30000},{1.20000}]}.
259
260param_select_real() ->
261    {selected,["field"],[{1.30000},{1.20000}]}.
262
263param_select_double() ->
264    {selected,["field"],[{1.30000},{1.20000}]}.
265
266param_select_mix() ->
267    {selected,["id","data"],[{1, "foo"}, {2, "bar"}]}.
268
269param_update() ->
270    {selected,["id","data"],[{3, "baz"},{1, "foobar"}, {2, "foobar"}]}.
271
272param_delete() ->
273    {selected,["id","data"],[{3, "baz"}]}.
274
275param_select() ->
276    {selected,["id","data"],[{1, "foo"},{3, "foo"}]}.
277
278%-------------------------------------------------------------------------
279describe_integer() ->
280    {ok,[{"myint1",sql_smallint},
281	 {"myint2",sql_integer},
282	 {"myint3",sql_integer}]}.
283
284describe_string() ->
285    {ok,[{"str1",{sql_char,10}},
286	 {"str2",{sql_char,10}},
287	 {"str3",{sql_varchar,10}},
288	 {"str4",{sql_varchar,10}}]}.
289
290describe_floating() ->
291    {ok,[{"f",sql_real},{"r",sql_real},{"d",{sql_float,17}}]}.
292describe_dec_num() ->
293    {ok,[{"mydec",{sql_numeric,9,3}},{"mynum",{sql_numeric,9,2}}]}.
294
295describe_timestamp() ->
296    {ok, [{"field", sql_timestamp}]}.
297
298%-------------------------------------------------------------------------
299drop_proc() ->
300    "drop function test_proc1(OUT integer, OUT integer);".
301
302stored_proc_integer_out() ->
303    "create or replace FUNCTION test_proc1(" ++
304        "OUT int_a INTEGER, " ++
305        "OUT int_b INTEGER) " ++
306        "AS $$ " ++
307        "BEGIN " ++
308        " int_a := 123; " ++
309        " int_b := 456; " ++
310        "END " ++
311        "$$ LANGUAGE plpgsql ".
312
313%% This does not test what you might think it is supposed to test.
314%% Since the stored procedure has got 2 out parameters and no
315%% in parameters it is of arity 0 as called below.
316%%
317%% The port program odbcserver.c will marshal these out parameters
318%% and hand them to ODBC. The ODBC driver for postgres will
319%% apparently not give a hoot about these out parameters and instead
320%% return the result in a regular result select set. The port program
321%% will assume it has the result in the out parameters and marshal
322%% these as they are i.e as it itself had packed them, so they
323%% come back unchanged.
324%%
325%% The real function result goes into the void but the code in odbcserver.c
326%% that marshals out parameters returned from ODBC will be run
327%% so that is what this test tests...
328%%
329param_query(Ref) ->
330    odbc:param_query(Ref, "select * from test_proc1()",
331                     [{sql_integer, out, [111]},
332                      {sql_integer, out, [444]}]).
333
334query_result() ->
335    {executed, 2, [{111, 444}]}.
336