22#include <stdio.h>
33#include <string.h>
44
5- #define MAX_QUERY_SIZE 65536 /* queries larger than this are rejected */
5+ #define MAX_QUERY_SIZE 65536 /* queries larger than this are rejected */
66
77#include "libpg_query/pg_query.h"
88
@@ -25,17 +25,38 @@ ERL_NIF_TERM make_binary(ErlNifEnv *env, char *source) {
2525 return binary ;
2626}
2727
28- static ERL_NIF_TERM max_query_size (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []) {
28+ ERL_NIF_TERM make_error_response (ErlNifEnv * env , char * message ) {
29+ ERL_NIF_TERM error_map = enif_make_new_map (env );
30+ if (!enif_make_map_put (env , error_map , enif_make_atom (env , "message" ),
31+ make_binary (env , message ), & error_map )) {
32+ return enif_raise_exception (env , make_binary (env , "failed to update map" ));
33+ }
34+ return error_map ;
35+ }
36+
37+ ERL_NIF_TERM query_too_long_error (ErlNifEnv * env , size_t query_size ) {
38+ char error_msg [128 ];
39+ snprintf (error_msg , 128 ,
40+ "cannot parse query: query size %lu is bigger than maximum size %i" ,
41+ query_size , MAX_QUERY_SIZE );
42+ ERL_NIF_TERM error_map = make_error_response (env , error_msg );
43+ return enif_make_tuple2 (env , enif_make_atom (env , "error" ), error_map );
44+ }
45+
46+
47+ static ERL_NIF_TERM max_query_size (ErlNifEnv * env , int argc ,
48+ const ERL_NIF_TERM argv []) {
2949 return enif_make_int64 (env , MAX_QUERY_SIZE );
3050}
3151
32- static ERL_NIF_TERM parse_query (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []) {
52+ static ERL_NIF_TERM parse_query (ErlNifEnv * env , int argc ,
53+ const ERL_NIF_TERM argv []) {
3354 ErlNifBinary query ;
3455 ERL_NIF_TERM term ;
3556
3657 if (argc == 1 && enif_inspect_binary (env , argv [0 ], & query )) {
3758 if (query .size >= MAX_QUERY_SIZE ) {
38- return enif_make_badarg (env );
59+ return query_too_long_error (env , query . size );
3960 }
4061
4162 // add one more byte for the null termination
@@ -49,27 +70,14 @@ static ERL_NIF_TERM parse_query(ErlNifEnv *env, int argc, const ERL_NIF_TERM arg
4970 PgQueryProtobufParseResult result = pg_query_parse_protobuf (statement );
5071
5172 if (result .error ) {
52- ERL_NIF_TERM error_map = enif_make_new_map (env );
53-
54- if (!enif_make_map_put (
55- env ,
56- error_map ,
57- enif_make_atom (env , "message" ),
58- make_binary (env , result .error -> message ),
59- & error_map
60- )) {
61- return enif_raise_exception (env , make_binary (env , "failed to update map" ));
62- }
63-
64- if (!enif_make_map_put (
65- env ,
66- error_map ,
67- enif_make_atom (env , "cursorpos" ),
68- // drop the cursorpos by one, so it's zero-indexed
69- enif_make_int (env , result .error -> cursorpos - 1 ),
70- & error_map
71- )) {
72- return enif_raise_exception (env , make_binary (env , "failed to update map" ));
73+ ERL_NIF_TERM error_map = make_error_response (env , result .error -> message );
74+
75+ if (!enif_make_map_put (env , error_map , enif_make_atom (env , "cursorpos" ),
76+ // drop the cursorpos by one, so it's zero-indexed
77+ enif_make_int (env , result .error -> cursorpos - 1 ),
78+ & error_map )) {
79+ return enif_raise_exception (env ,
80+ make_binary (env , "failed to update map" ));
7381 }
7482
7583 term = enif_make_tuple2 (env , enif_make_atom (env , "error" ), error_map );
@@ -86,7 +94,7 @@ static ERL_NIF_TERM parse_query(ErlNifEnv *env, int argc, const ERL_NIF_TERM arg
8694}
8795
8896static ERL_NIF_TERM deparse_query (ErlNifEnv * env , int argc ,
89- const ERL_NIF_TERM argv []) {
97+ const ERL_NIF_TERM argv []) {
9098 ErlNifBinary proto ;
9199 ERL_NIF_TERM term ;
92100
@@ -98,17 +106,8 @@ static ERL_NIF_TERM deparse_query(ErlNifEnv *env, int argc,
98106 PgQueryDeparseResult result = pg_query_deparse_protobuf (parse_tree );
99107
100108 if (result .error ) {
101- ERL_NIF_TERM error_map = enif_make_new_map (env );
102-
103- if (!enif_make_map_put (
104- env ,
105- error_map ,
106- enif_make_atom (env , "message" ),
107- make_binary (env , result .error -> message ),
108- & error_map
109- )) {
110- return enif_raise_exception (env , make_binary (env , "failed to update map" ));
111- }
109+ ERL_NIF_TERM error_map = make_error_response (env , result .error -> message );
110+
112111
113112 term = enif_make_tuple2 (env , enif_make_atom (env , "error" ), error_map );
114113 } else {
@@ -123,13 +122,13 @@ static ERL_NIF_TERM deparse_query(ErlNifEnv *env, int argc,
123122}
124123
125124static ERL_NIF_TERM scan_query (ErlNifEnv * env , int argc ,
126- const ERL_NIF_TERM argv []) {
125+ const ERL_NIF_TERM argv []) {
127126 ErlNifBinary query ;
128127 ERL_NIF_TERM term ;
129128
130129 if (argc == 1 && enif_inspect_binary (env , argv [0 ], & query )) {
131130 if (query .size >= MAX_QUERY_SIZE ) {
132- return enif_make_badarg (env );
131+ return query_too_long_error (env , query . size );
133132 }
134133
135134 // add one more byte for the null termination
@@ -143,27 +142,15 @@ static ERL_NIF_TERM scan_query(ErlNifEnv *env, int argc,
143142 PgQueryScanResult result = pg_query_scan (statement );
144143
145144 if (result .error ) {
146- ERL_NIF_TERM error_map = enif_make_new_map (env );
147-
148- if (!enif_make_map_put (
149- env ,
150- error_map ,
151- enif_make_atom (env , "message" ),
152- make_binary (env , result .error -> message ),
153- & error_map
154- )) {
155- return enif_raise_exception (env , make_binary (env , "failed to update map" ));
156- }
157-
158- if (result .error -> cursorpos > 0 && !enif_make_map_put (
159- env ,
160- error_map ,
161- enif_make_atom (env , "cursorpos" ),
162- // drop the cursorpos by one, so it's zero-indexed
163- enif_make_int (env , result .error -> cursorpos - 1 ),
164- & error_map
165- )) {
166- return enif_raise_exception (env , make_binary (env , "failed to update map" ));
145+ ERL_NIF_TERM error_map = make_error_response (env , result .error -> message );
146+
147+ if (result .error -> cursorpos > 0 &&
148+ !enif_make_map_put (env , error_map , enif_make_atom (env , "cursorpos" ),
149+ // drop the cursorpos by one, so it's zero-indexed
150+ enif_make_int (env , result .error -> cursorpos - 1 ),
151+ & error_map )) {
152+ return enif_raise_exception (env ,
153+ make_binary (env , "failed to update map" ));
167154 }
168155
169156 term = enif_make_tuple2 (env , enif_make_atom (env , "error" ), error_map );
@@ -179,10 +166,10 @@ static ERL_NIF_TERM scan_query(ErlNifEnv *env, int argc,
179166}
180167
181168static ErlNifFunc funcs [] = {
182- {"parse_query" , 1 , parse_query },
183- {"deparse_query" , 1 , deparse_query },
184- {"scan_query" , 1 , scan_query },
185- {"max_query_size" , 0 , max_query_size },
169+ {"parse_query" , 1 , parse_query },
170+ {"deparse_query" , 1 , deparse_query },
171+ {"scan_query" , 1 , scan_query },
172+ {"max_query_size" , 0 , max_query_size },
186173};
187174
188175ERL_NIF_INIT (Elixir .PgQuery .Parser , funcs , NULL , NULL , NULL , NULL )
0 commit comments