Mercurial > urweb
comparison src/cjr_print.sml @ 282:0236d9412ad2
Ran a prepared statement with one string parameter
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sun, 07 Sep 2008 09:28:13 -0400 |
parents | fdd7a698be01 |
children | c0e4ac23522d |
comparison
equal
deleted
inserted
replaced
281:7d5860add50f | 282:0236d9412ad2 |
---|---|
331 string " ? lw_Basis_True : lw_Basis_False)"] | 331 string " ? lw_Basis_True : lw_Basis_False)"] |
332 | _ => (ErrorMsg.errorAt loc "Don't know how to unmarshal type from SQL"; | 332 | _ => (ErrorMsg.errorAt loc "Don't know how to unmarshal type from SQL"; |
333 Print.eprefaces' [("Type", p_typ env tAll)]; | 333 Print.eprefaces' [("Type", p_typ env tAll)]; |
334 string "ERROR") | 334 string "ERROR") |
335 | 335 |
336 datatype sql_type = | |
337 Int | |
338 | Float | |
339 | String | |
340 | Bool | |
341 | |
342 fun p_sql_type t = | |
343 string (case t of | |
344 Int => "lw_Basis_int" | |
345 | Float => "lw_Basis_float" | |
346 | String => "lw_Basis_string" | |
347 | Bool => "lw_Basis_bool") | |
348 | |
349 fun getPargs (e, _) = | |
350 case e of | |
351 EPrim (Prim.String _) => [] | |
352 | EFfiApp ("Basis", "strcat", [e1, e2]) => getPargs e1 @ getPargs e2 | |
353 | |
354 | EFfiApp ("Basis", "sqlifyInt", [e]) => [(e, Int)] | |
355 | EFfiApp ("Basis", "sqlifyFloat", [e]) => [(e, Float)] | |
356 | EFfiApp ("Basis", "sqlifyString", [e]) => [(e, String)] | |
357 | EFfiApp ("Basis", "sqlifyBool", [e]) => [(e, Bool)] | |
358 | |
359 | _ => raise Fail "CjrPrint: getPargs" | |
360 | |
361 fun p_ensql t e = | |
362 case t of | |
363 Int => box [string "(char *)&", e] | |
364 | Float => box [string "(char *)&", e] | |
365 | String => e | |
366 | Bool => box [string "lw_Basis_ensqlBool(", e, string ")"] | |
367 | |
368 fun p_ensql_len t e = | |
369 case t of | |
370 Int => string "sizeof(lw_Basis_int)" | |
371 | Float => string "sizeof(lw_Basis_float)" | |
372 | String => box [string "strlen(", e, string ")"] | |
373 | Bool => string "sizeof(lw_Basis_bool)" | |
374 | |
336 fun p_exp' par env (e, loc) = | 375 fun p_exp' par env (e, loc) = |
337 case e of | 376 case e of |
338 EPrim p => Prim.p_t_GCC p | 377 EPrim p => Prim.p_t_GCC p |
339 | ERel n => p_rel env n | 378 | ERel n => p_rel env n |
340 | ENamed n => p_enamed env n | 379 | ENamed n => p_enamed env n |
558 p_exp (E.pushERel env x t) e2, | 597 p_exp (E.pushERel env x t) e2, |
559 string ";", | 598 string ";", |
560 newline, | 599 newline, |
561 string "})"] | 600 string "})"] |
562 | 601 |
563 | EQuery {exps, tables, rnum, state, query, body, initial} => | 602 | EQuery {exps, tables, rnum, state, query, body, initial, prepared} => |
564 let | 603 let |
565 val exps = map (fn (x, t) => ("__lwf_" ^ x, t)) exps | 604 val exps = map (fn (x, t) => ("__lwf_" ^ x, t)) exps |
566 val tables = ListUtil.mapConcat (fn (x, xts) => | 605 val tables = ListUtil.mapConcat (fn (x, xts) => |
567 map (fn (x', t) => ("__lwf_" ^ x ^ ".__lwf_" ^ x', t)) xts) | 606 map (fn (x', t) => ("__lwf_" ^ x ^ ".__lwf_" ^ x', t)) xts) |
568 tables | 607 tables |
571 in | 610 in |
572 box [string "({", | 611 box [string "({", |
573 newline, | 612 newline, |
574 string "PGconn *conn = lw_get_db(ctx);", | 613 string "PGconn *conn = lw_get_db(ctx);", |
575 newline, | 614 newline, |
576 string "char *query = ", | 615 case prepared of |
577 p_exp env query, | 616 NONE => box [string "char *query = ", |
578 string ";", | 617 p_exp env query, |
579 newline, | 618 string ";", |
619 newline] | |
620 | SOME _ => | |
621 let | |
622 val ets = getPargs query | |
623 in | |
624 box [p_list_sepi newline | |
625 (fn i => fn (e, t) => | |
626 box [p_sql_type t, | |
627 space, | |
628 string "arg", | |
629 string (Int.toString (i + 1)), | |
630 space, | |
631 string "=", | |
632 space, | |
633 p_exp env e, | |
634 string ";"]) | |
635 ets, | |
636 newline, | |
637 newline, | |
638 | |
639 string "const char *paramValues[] = { ", | |
640 p_list_sepi (box [string ",", space]) | |
641 (fn i => fn (_, t) => p_ensql t (box [string "arg", | |
642 string (Int.toString (i + 1))])) | |
643 ets, | |
644 string " };", | |
645 newline, | |
646 newline, | |
647 | |
648 string "const int paramLengths[] = { ", | |
649 p_list_sepi (box [string ",", space]) | |
650 (fn i => fn (_, t) => p_ensql_len t (box [string "arg", | |
651 string (Int.toString (i + 1))])) | |
652 ets, | |
653 string " };", | |
654 newline, | |
655 newline, | |
656 | |
657 string "const static int paramFormats[] = { ", | |
658 p_list_sep (box [string ",", space]) (fn _ => string "1") ets, | |
659 string " };", | |
660 newline, | |
661 newline] | |
662 end, | |
580 string "int n, i;", | 663 string "int n, i;", |
581 newline, | 664 newline, |
582 p_typ env state, | 665 p_typ env state, |
583 space, | 666 space, |
584 string "acc", | 667 string "acc", |
586 string "=", | 669 string "=", |
587 space, | 670 space, |
588 p_exp env initial, | 671 p_exp env initial, |
589 string ";", | 672 string ";", |
590 newline, | 673 newline, |
591 string "PGresult *res = PQexecParams(conn, query, 0, NULL, NULL, NULL, NULL, 1);", | 674 string "PGresult *res = ", |
675 case prepared of | |
676 NONE => string "PQexecParams(conn, query, 0, NULL, NULL, NULL, NULL, 1);" | |
677 | SOME n => box [string "PQexecPrepared(conn, \"lw", | |
678 string (Int.toString n), | |
679 string "\", ", | |
680 string (Int.toString (length (getPargs query))), | |
681 string ", paramValues, paramLengths, paramFormats, 1);"], | |
592 newline, | 682 newline, |
593 newline, | 683 newline, |
594 | 684 |
595 string "if (res == NULL) lw_error(ctx, FATAL, \"Out of memory allocating query result.\");", | 685 string "if (res == NULL) lw_error(ctx, FATAL, \"Out of memory allocating query result.\");", |
596 newline, | 686 newline, |
600 newline, | 690 newline, |
601 box [string "PQclear(res);", | 691 box [string "PQclear(res);", |
602 newline, | 692 newline, |
603 string "lw_error(ctx, FATAL, \"", | 693 string "lw_error(ctx, FATAL, \"", |
604 string (ErrorMsg.spanToString loc), | 694 string (ErrorMsg.spanToString loc), |
605 string ": Query failed:\\n%s\\n%s\", query, PQerrorMessage(conn));", | 695 string ": Query failed:\\n%s\\n%s\", ", |
696 case prepared of | |
697 NONE => string "query" | |
698 | SOME _ => p_exp env query, | |
699 string ", PQerrorMessage(conn));", | |
606 newline], | 700 newline], |
607 string "}", | 701 string "}", |
608 newline, | 702 newline, |
609 newline, | 703 newline, |
610 | 704 |
811 | DTable (x, _) => box [string "/* SQL table ", | 905 | DTable (x, _) => box [string "/* SQL table ", |
812 string x, | 906 string x, |
813 string " */", | 907 string " */", |
814 newline] | 908 newline] |
815 | DDatabase s => box [string "static void lw_db_validate(lw_context);", | 909 | DDatabase s => box [string "static void lw_db_validate(lw_context);", |
910 newline, | |
911 string "static void lw_db_prepare(lw_context);", | |
816 newline, | 912 newline, |
817 newline, | 913 newline, |
818 string "void lw_db_init(lw_context ctx) {", | 914 string "void lw_db_init(lw_context ctx) {", |
819 newline, | 915 newline, |
820 string "PGconn *conn = PQconnectdb(\"", | 916 string "PGconn *conn = PQconnectdb(\"", |
841 newline, | 937 newline, |
842 string "lw_set_db(ctx, conn);", | 938 string "lw_set_db(ctx, conn);", |
843 newline, | 939 newline, |
844 string "lw_db_validate(ctx);", | 940 string "lw_db_validate(ctx);", |
845 newline, | 941 newline, |
942 string "lw_db_prepare(ctx);", | |
943 newline, | |
846 string "}", | 944 string "}", |
847 newline, | 945 newline, |
848 newline, | 946 newline, |
849 string "void lw_db_close(lw_context ctx) {", | 947 string "void lw_db_close(lw_context ctx) {", |
850 newline, | 948 newline, |
851 string "PQfinish(lw_get_db(ctx));", | 949 string "PQfinish(lw_get_db(ctx));", |
852 newline, | 950 newline, |
853 string "}", | 951 string "}", |
854 newline] | 952 newline] |
953 | |
954 | DPreparedStatements ss => | |
955 box [string "static void lw_db_prepare(lw_context ctx) {", | |
956 newline, | |
957 string "PGconn *conn = lw_get_db(ctx);", | |
958 newline, | |
959 string "PGresult *res;", | |
960 newline, | |
961 newline, | |
962 | |
963 p_list_sepi newline (fn i => fn (s, n) => | |
964 box [string "res = PQprepare(conn, \"lw", | |
965 string (Int.toString i), | |
966 string "\", \"", | |
967 string (String.toString s), | |
968 string "\", ", | |
969 string (Int.toString n), | |
970 string ", NULL);", | |
971 newline, | |
972 string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {", | |
973 newline, | |
974 box [string "char msg[1024];", | |
975 newline, | |
976 string "strncpy(msg, PQerrorMessage(conn), 1024);", | |
977 newline, | |
978 string "msg[1023] = 0;", | |
979 newline, | |
980 string "PQclear(res);", | |
981 newline, | |
982 string "PQfinish(conn);", | |
983 newline, | |
984 string "lw_error(ctx, FATAL, \"Unable to create prepared statement:\\n", | |
985 string (String.toString s), | |
986 string "\\n%s\", msg);", | |
987 newline], | |
988 string "}", | |
989 newline, | |
990 string "PQclear(res);", | |
991 newline]) | |
992 ss, | |
993 | |
994 string "}"] | |
855 | 995 |
856 datatype 'a search = | 996 datatype 'a search = |
857 Found of 'a | 997 Found of 'a |
858 | NotFound | 998 | NotFound |
859 | Error | 999 | Error |