5252 to_string_literal /2 ,
5353 to_string_literal_t /1 ,
5454 to_bool /1 ,
55+ to_timestamp /2 ,
5556 sqlite_db /1 ,
5657 sqlite_file /1 ,
5758 encode_term /1 ,
@@ -286,6 +287,23 @@ to_bool(true) -> true;
286287to_bool (1 ) -> true ;
287288to_bool (_ ) -> false .
288289
290+ escape_timestamp ({{Y , Mo , D }, {H , Mi , S }}) ->
291+ list_to_binary (io_lib :format (" ~4..0B -~2..0B -~2..0B "
292+ " ~2..0B :~2..0B :~2..0B " ,
293+ [Y , Mo , D , H , Mi , S ])).
294+
295+
296+ to_timestamp ({Y , {H , M , S , _ }}, mysql_prepared ) -> {Y , {H , M , S }};
297+ to_timestamp (<<TS :64 /signed -big -integer >>, pgsql_prepared ) ->
298+ calendar :gregorian_seconds_to_datetime (
299+ calendar :datetime_to_gregorian_seconds ({{2000 , 1 , 1 }, {0 , 0 , 0 }}) + TS div 1_000_000 );
300+ to_timestamp (<<Y :4 /binary , $- , Mo :2 /binary , $- , D :2 /binary , " " ,
301+ H :2 /binary , $: , Mi :2 /binary , $: , S :2 /binary >>,
302+ _ ) ->
303+ {{binary_to_integer (Y ), binary_to_integer (Mo ), binary_to_integer (D )},
304+ {binary_to_integer (H ), binary_to_integer (Mi ), binary_to_integer (S )}}.
305+
306+
289307to_list (EscapeFun , Val ) ->
290308 Escaped = lists :join (<<" ," >>, lists :map (EscapeFun , Val )),
291309 [<<" (" >>, Escaped , <<" )" >>].
@@ -813,7 +831,8 @@ select_sql_query([{_, _} | Rest], Type, Version, Query) ->
813831generic_sql_query (SQLQuery ) ->
814832 sql_query_format_res (
815833 sql_query_internal (generic_sql_query_format (SQLQuery )),
816- SQLQuery ).
834+ SQLQuery ,
835+ generic ).
817836
818837generic_sql_query_format (SQLQuery ) ->
819838 Args = (SQLQuery # sql_query .args )(generic_escape ()),
@@ -825,14 +844,16 @@ generic_escape() ->
825844 boolean = fun (true ) -> <<" 1" >>;
826845 (false ) -> <<" 0" >>
827846 end ,
847+ timestamp = fun (X ) -> <<" '" , (escape_timestamp (X ))/binary , " '" >> end ,
828848 in_array_string = fun (X ) -> <<" '" , (escape (X ))/binary , " '" >> end ,
829849 like_escape = fun () -> <<" " >> end
830850 }.
831851
832852pgsql_sql_query (SQLQuery ) ->
833853 sql_query_format_res (
834854 sql_query_internal (pgsql_sql_query_format (SQLQuery )),
835- SQLQuery ).
855+ SQLQuery ,
856+ pgsql ).
836857
837858pgsql_sql_query_format (SQLQuery ) ->
838859 Args = (SQLQuery # sql_query .args )(pgsql_escape ()),
@@ -844,14 +865,16 @@ pgsql_escape() ->
844865 boolean = fun (true ) -> <<" 't'" >>;
845866 (false ) -> <<" 'f'" >>
846867 end ,
868+ timestamp = fun (X ) -> <<" E'" , (escape_timestamp (X ))/binary , " '" >> end ,
847869 in_array_string = fun (X ) -> <<" E'" , (escape (X ))/binary , " '" >> end ,
848870 like_escape = fun () -> <<" ESCAPE E'\\\\ '" >> end
849871 }.
850872
851873sqlite_sql_query (SQLQuery ) ->
852874 sql_query_format_res (
853875 sql_query_internal (sqlite_sql_query_format (SQLQuery )),
854- SQLQuery ).
876+ SQLQuery ,
877+ sqlite ).
855878
856879sqlite_sql_query_format (SQLQuery ) ->
857880 Args = (SQLQuery # sql_query .args )(sqlite_escape ()),
@@ -863,6 +886,7 @@ sqlite_escape() ->
863886 boolean = fun (true ) -> <<" 1" >>;
864887 (false ) -> <<" 0" >>
865888 end ,
889+ timestamp = fun (X ) -> <<" '" , (escape_timestamp (X ))/binary , " '" >> end ,
866890 in_array_string = fun (X ) -> <<" '" , (standard_escape (X ))/binary , " '" >> end ,
867891 like_escape = fun () -> <<" ESCAPE '\\ '" >> end
868892 }.
@@ -894,12 +918,15 @@ pgsql_prepare(SQLQuery, State) ->
894918 Query = (SQLQuery # sql_query .format_query )(Args ),
895919 pgsql :prepare (State # state .db_ref , SQLQuery # sql_query .hash , Query ).
896920
921+
897922pgsql_execute_escape () ->
898- # sql_escape {string = fun (X ) -> X end ,
899- integer = fun (X ) -> [misc :i2l (X )] end ,
900- boolean = fun (true ) -> " 1" ;
901- (false ) -> " 0"
902- end ,
923+ # sql_escape {
924+ string = fun (X ) -> X end ,
925+ integer = fun (X ) -> misc :i2l (X ) end ,
926+ boolean = fun (true ) -> <<" 1" >>;
927+ (false ) -> <<" 0" >>
928+ end ,
929+ timestamp = fun escape_timestamp /1 ,
903930 in_array_string = fun (X ) -> <<" \" " , (escape (X ))/binary , " \" " >> end ,
904931 like_escape = fun () -> ignore end
905932 }.
@@ -913,33 +940,46 @@ pgsql_execute_sql_query(SQLQuery, State) ->
913940% timer:tc(pgsql, execute, [State#state.db_ref, SQLQuery#sql_query.hash, Args]),
914941% io:format("T ~ts ~p~n", [SQLQuery#sql_query.hash, T]),
915942 Res = pgsql_execute_to_odbc (ExecuteRes ),
916- sql_query_format_res (Res , SQLQuery ).
943+ sql_query_format_res (Res , SQLQuery , pgsql_prepared ).
944+
917945
918946mysql_prepared_execute (# sql_query {hash = Hash } = Query , State ) ->
919- ValEsc = # sql_escape {like_escape = fun () -> ignore end , _ = fun (X ) -> X end },
920- TypesEsc = # sql_escape {string = fun (_ ) -> string end ,
921- integer = fun (_ ) -> integer end ,
922- boolean = fun (_ ) -> bool end ,
947+ ValEsc = # sql_escape {
948+ like_escape = fun () -> ignore end ,
949+ timestamp = fun escape_timestamp /1 ,
950+ _ = fun (X ) -> X end
951+ },
952+ TypesEsc = # sql_escape {
953+ string = fun (_ ) -> string end ,
954+ integer = fun (_ ) -> integer end ,
955+ boolean = fun (_ ) -> bool end ,
956+ timestamp = fun (_ ) -> string end ,
923957 in_array_string = fun (_ ) -> string end ,
924958 like_escape = fun () -> ignore end },
925959 Val = [X || X <- (Query # sql_query .args )(ValEsc ), X /= ignore ],
926960 Types = [X || X <- (Query # sql_query .args )(TypesEsc ), X /= ignore ],
927961 QueryFn = fun () ->
928- PrepEsc = # sql_escape {like_escape = fun () -> <<>> end , _ = fun (_ ) -> <<" ?" >> end },
929- (Query # sql_query .format_query )((Query # sql_query .args )(PrepEsc ))
930- end ,
962+ PrepEsc = # sql_escape {like_escape = fun () -> <<>> end , _ = fun (_ ) -> <<" ?" >> end },
963+ (Query # sql_query .format_query )((Query # sql_query .args )(PrepEsc ))
964+ end ,
931965 QueryTimeout = query_timeout (State # state .host ),
932- Res = p1_mysql_conn :prepared_query (State # state .db_ref , QueryFn , Hash , Val , Types ,
933- self (), [{timeout , QueryTimeout - 1000 }]),
966+ Res = p1_mysql_conn :prepared_query (State # state .db_ref ,
967+ QueryFn ,
968+ Hash ,
969+ Val ,
970+ Types ,
971+ self (),
972+ [{timeout , QueryTimeout - 1000 }]),
934973 Res2 = mysql_to_odbc (Res ),
935- sql_query_format_res (Res2 , Query ).
974+ sql_query_format_res (Res2 , Query , mysql_prepared ).
975+
936976
937- sql_query_format_res ({selected , _ , Rows }, SQLQuery ) ->
977+ sql_query_format_res ({selected , _ , Rows }, SQLQuery , DbType ) ->
938978 Res =
939979 lists :flatmap (
940980 fun (Row ) ->
941981 try
942- [(SQLQuery # sql_query .format_res )(Row )]
982+ [(SQLQuery # sql_query .format_res )(Row , DbType )]
943983 catch
944984 Class :Reason :StackTrace ->
945985 ? ERROR_MSG (" Error while processing SQL query result:~n "
@@ -950,7 +990,7 @@ sql_query_format_res({selected, _, Rows}, SQLQuery) ->
950990 end
951991 end , Rows ),
952992 {selected , Res };
953- sql_query_format_res (Res , _SQLQuery ) ->
993+ sql_query_format_res (Res , _SQLQuery , _DbType ) ->
954994 Res .
955995
956996sql_query_to_iolist (SQLQuery ) ->
0 commit comments