diff: improvements to ODBC interface
Simon Taylor
stayl at cs.mu.oz.au
Sat Oct 4 20:50:40 AEST 1997
Estimated hours taken: 1
Improve the ODBC interface slightly.
extras/odbc.m
Remove odbc__execute/4. Add odbc__solutions/4 to collect all the
results for a query into a list and odbc__aggregate/6 similar
to std_util:unsorted_aggregate/4.
Index: odbc.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/extras/odbc/odbc.m,v
retrieving revision 1.1
diff -u -r1.1 odbc.m
--- odbc.m 1997/10/02 01:51:37 1.1
+++ odbc.m 1997/10/04 10:29:04
@@ -96,20 +96,29 @@
; float(float)
; time(string). % Time string: "YYYY-MM-DD hh:mm:ss.mmm"
- % The odbc__state arguments threaded through odbc__execute/4 and
- % odbc__execute/3 enforce the restriction that database activity can
- % only occur within a transaction, since odbc__states are only
- % available to the closure called by odbc__transaction/5.
-
- % Execute a command, returning a list of results.
-:- pred odbc__execute(string, list(odbc__row), odbc__state, odbc__state).
-:- mode odbc__execute(in, out, di, uo) is det.
+ % The odbc__state arguments threaded through these predicates
+ % enforce the restriction that database activity can only occur
+ % within a transaction, since odbc__states are only available
+ % to the closure called by odbc__transaction/5.
% Execute an SQL statement which doesn't return any results, such
% as DELETE.
:- pred odbc__execute(string, odbc__state, odbc__state).
:- mode odbc__execute(in, di, uo) is det.
+ % Execute an SQL statement, returning a list of results in the
+ % order they are returned from the database.
+:- pred odbc__solutions(string, list(odbc__row), odbc__state, odbc__state).
+:- mode odbc__solutions(in, out, di, uo) is det.
+
+ % Execute an SQL statement, applying the accumulator predicate
+ % to each element of the result set as it is returned from
+ % the database.
+:- pred odbc__aggregate(string, pred(odbc__row, T, T), T, T,
+ odbc__state, odbc__state).
+:- mode odbc__aggregate(in, pred(in, in, out) is det, in, out, di, uo) is det.
+:- mode odbc__aggregate(in, pred(in, di, uo) is det, di, uo, di, uo) is det.
+
%-----------------------------------------------------------------------------%
% Predicates and types to get information about database tables.
@@ -708,49 +717,75 @@
odbc__execute_statement(SQLString, Statement0, Statement),
odbc__cleanup_statement_check_error(Statement).
-odbc__execute(SQLString, Results) -->
- odbc__get_result_set(odbc__execute_statement(SQLString), Results).
+odbc__solutions(SQLString, Results) -->
+ % XXX optimize this when we have better support
+ % for last call optimization.
+ odbc__do_aggregate(odbc__execute_statement(SQLString),
+ cons, [], Results0),
+ { list__reverse(Results0, Results) }.
+
+odbc__aggregate(SQLString, Accumulator, Acc0, Acc) -->
+ odbc__do_aggregate(odbc__execute_statement(SQLString),
+ Accumulator, Acc0, Acc).
+
+:- pred cons(T, list(T), list(T)).
+:- mode cons(in, in, out) is det.
+
+cons(H, T, [H|T]).
%-----------------------------------------------------------------------------%
-:- pred odbc__get_result_set(pred(odbc__statement, odbc__statement,
- odbc__state, odbc__state),
- list(odbc__row), odbc__state, odbc__state).
-:- mode odbc__get_result_set(pred(di, uo, di, uo) is det, out, di, uo) is det.
+:- pred odbc__do_aggregate(pred(odbc__statement, odbc__statement,
+ odbc__state, odbc__state), pred(odbc__row, T, T),
+ T, T, odbc__state, odbc__state).
+:- mode odbc__do_aggregate(pred(di, uo, di, uo) is det,
+ pred(in, in, out) is det,
+ in, out, di, uo) is det.
+:- mode odbc__do_aggregate(pred(di, uo, di, uo) is det,
+ pred(in, di, uo) is det,
+ di, uo, di, uo) is det.
-odbc__get_result_set(Execute, Results) -->
+odbc__do_aggregate(Execute, Accumulate, Result0, Result) -->
odbc__alloc_statement(Statement0),
call(Execute, Statement0, Statement1),
odbc__bind_columns(Statement1, Statement2),
- odbc__get_rows(Results, Statement2, Statement),
+ odbc__get_rows(Accumulate, Result0, Result, Statement2, Statement),
odbc__cleanup_statement_check_error(Statement).
%-----------------------------------------------------------------------------%
% Get the set of result rows from the statement.
-:- pred odbc__get_rows(list(odbc__row), odbc__statement, odbc__statement,
- odbc__state, odbc__state).
-:- mode odbc__get_rows(out, di, uo, di, uo) is det.
+:- pred odbc__get_rows(pred(odbc__row, T, T), T, T,
+ odbc__statement, odbc__statement, odbc__state, odbc__state).
+:- mode odbc__get_rows(pred(in, in, out) is det, in, out,
+ di, uo, di, uo) is det.
+:- mode odbc__get_rows(pred(in, di, uo) is det, di, uo, di, uo, di, uo) is det.
-odbc__get_rows(Rows, Statement0, Statement) -->
+odbc__get_rows(Accumulate, Result0, Result, Statement0, Statement) -->
odbc__get_number_of_columns(NumColumns, Statement0, Statement1),
- odbc__get_rows_2(NumColumns, Rows, Statement1, Statement).
+ odbc__get_rows_2(NumColumns, Accumulate, Result0, Result,
+ Statement1, Statement).
-:- pred odbc__get_rows_2(int, list(odbc__row), odbc__statement,
- odbc__statement, odbc__state, odbc__state).
-:- mode odbc__get_rows_2(in, out, di, uo, di, uo) is det.
+:- pred odbc__get_rows_2(int, pred(odbc__row, T, T), T, T,
+ odbc__statement, odbc__statement, odbc__state, odbc__state).
+:- mode odbc__get_rows_2(in, pred(in, in, out) is det, in, out,
+ di, uo, di, uo) is det.
+:- mode odbc__get_rows_2(in, pred(in, di, uo) is det, di, uo,
+ di, uo, di, uo) is det.
-odbc__get_rows_2(NumColumns, Rows, Statement0, Statement) -->
+odbc__get_rows_2(NumColumns, Accumulate, Result0, Result,
+ Statement0, Statement) -->
% Try to fetch a new row.
odbc__fetch(Statement0, Statement1, Status),
( { odbc__no_data(Status) } ->
- { Rows = [] },
+ { Result = Result0 },
{ Statement = Statement1 }
;
odbc__get_attributes(1, NumColumns, Row,
Statement1, Statement2),
- odbc__get_rows_2(NumColumns, Rows1, Statement2, Statement),
- { Rows = [Row | Rows1] }
+ { Accumulate(Row, Result0, Result1) },
+ odbc__get_rows_2(NumColumns, Accumulate,
+ Result1, Result, Statement2, Statement)
).
%-----------------------------------------------------------------------------%
@@ -1960,35 +1995,35 @@
QualifierStatus) },
{ odbc__convert_pattern_argument(Owner, OwnerStr, OwnerStatus) },
{ odbc__convert_pattern_argument(TableName, TableStr, TableStatus) },
- odbc__get_result_set(odbc__sql_tables(QualifierStr, QualifierStatus,
- OwnerStr, OwnerStatus, TableStr, TableStatus), Results),
- list__map_foldl(odbc__convert_table_desc, Results, Tables).
+ odbc__do_aggregate(odbc__sql_tables(QualifierStr, QualifierStatus,
+ OwnerStr, OwnerStatus, TableStr, TableStatus),
+ cons, [], Results0),
+ { list__reverse(Results0, Results) },
+ ( { list__map(odbc__convert_table_desc, Results, Tables0) } ->
+ { Tables = Tables0 }
+ ;
+ odbc__add_message(error(internal_error) -
+ "[Mercury][odbc.m]Invalid results from SQLTables."),
+ odbc__throw
+ ).
-:- pred odbc__convert_table_desc(odbc__row, odbc__table_desc,
- odbc__state, odbc__state).
-:- mode odbc__convert_table_desc(in, out, di, uo) is det.
+:- pred odbc__convert_table_desc(odbc__row, odbc__table_desc).
+:- mode odbc__convert_table_desc(in, out) is semidet.
-odbc__convert_table_desc(Row0, Table) -->
- { NullToEmptyStr =
+odbc__convert_table_desc(Row0, Table) :-
+ NullToEmptyStr =
lambda([Data0::in, Data::out] is det, (
( Data0 = null ->
Data = string("")
;
Data = Data0
)
- )) },
- { list__map(NullToEmptyStr, Row0, Row) },
- (
- { Row = [string(Qualifier), string(Owner), string(Name),
- string(Type), string(Description) | DriverColumns] }
- ->
- { Table = odbc__table_desc(Qualifier, Owner, Name,
- Type, Description, DriverColumns) }
- ;
- odbc__add_message(error(internal_error) -
- "[Mercury][odbc.m]Invalid results from SQLTables."),
- odbc__throw
- ).
+ )),
+ list__map(NullToEmptyStr, Row0, Row),
+ Row = [string(Qualifier), string(Owner), string(Name),
+ string(Type), string(Description) | DriverColumns],
+ Table = odbc__table_desc(Qualifier, Owner, Name,
+ Type, Description, DriverColumns).
%-----------------------------------------------------------------------------%
Index: odbc_test.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/extras/odbc/odbc_test.m,v
retrieving revision 1.1
diff -u -r1.1 odbc_test.m
--- odbc_test.m 1997/10/02 01:51:41 1.1
+++ odbc_test.m 1997/10/04 09:27:08
@@ -72,7 +72,7 @@
odbc__state::di, odbc__state::uo) is det.
test_trans(Results) -->
- odbc__execute("select * from test", Results).
+ odbc__solutions("select * from test", Results).
:- pred output_results(list(odbc__row)::in,
io__state::di, io__state::uo) is det.
More information about the developers
mailing list