11#include "pg_query.h"
2+ #include "postgres_deparse.h"
23#include "xxhash/xxhash.h"
34#include <ruby.h>
45
@@ -10,6 +11,8 @@ void raise_ruby_split_error(PgQuerySplitResult result);
1011
1112VALUE pg_query_ruby_parse_protobuf (VALUE self , VALUE input );
1213VALUE pg_query_ruby_deparse_protobuf (VALUE self , VALUE input );
14+ VALUE pg_query_ruby_deparse_protobuf_opts (VALUE self , VALUE input , VALUE pretty_print , VALUE comments , VALUE indent_size , VALUE max_line_length , VALUE trailing_newline , VALUE commas_start_of_line );
15+ VALUE pg_query_ruby_deparse_comments_for_query (VALUE self , VALUE input );
1316VALUE pg_query_ruby_normalize (VALUE self , VALUE input );
1417VALUE pg_query_ruby_fingerprint (VALUE self , VALUE input );
1518VALUE pg_query_ruby_scan (VALUE self , VALUE input );
@@ -24,6 +27,8 @@ __attribute__((visibility ("default"))) void Init_pg_query(void)
2427
2528 rb_define_singleton_method (cPgQuery , "parse_protobuf" , pg_query_ruby_parse_protobuf , 1 );
2629 rb_define_singleton_method (cPgQuery , "deparse_protobuf" , pg_query_ruby_deparse_protobuf , 1 );
30+ rb_define_singleton_method (cPgQuery , "deparse_protobuf_opts" , pg_query_ruby_deparse_protobuf_opts , 7 );
31+ rb_define_singleton_method (cPgQuery , "deparse_comments_for_query" , pg_query_ruby_deparse_comments_for_query , 1 );
2732 rb_define_singleton_method (cPgQuery , "normalize" , pg_query_ruby_normalize , 1 );
2833 rb_define_singleton_method (cPgQuery , "fingerprint" , pg_query_ruby_fingerprint , 1 );
2934 rb_define_singleton_method (cPgQuery , "_raw_scan" , pg_query_ruby_scan , 1 );
@@ -70,6 +75,24 @@ void raise_ruby_deparse_error(PgQueryDeparseResult result)
7075 rb_exc_raise (rb_class_new_instance (4 , args , cParseError ));
7176}
7277
78+ void raise_ruby_deparse_comments_error (PgQueryDeparseCommentsResult result )
79+ {
80+ VALUE cPgQuery , cParseError ;
81+ VALUE args [4 ];
82+
83+ cPgQuery = rb_const_get (rb_cObject , rb_intern ("PgQuery" ));
84+ cParseError = rb_const_get_at (cPgQuery , rb_intern ("ParseError" ));
85+
86+ args [0 ] = rb_str_new2 (result .error -> message );
87+ args [1 ] = rb_str_new2 (result .error -> filename );
88+ args [2 ] = INT2NUM (result .error -> lineno );
89+ args [3 ] = INT2NUM (result .error -> cursorpos );
90+
91+ pg_query_free_deparse_comments_result (result );
92+
93+ rb_exc_raise (rb_class_new_instance (4 , args , cParseError ));
94+ }
95+
7396void raise_ruby_normalize_error (PgQueryNormalizeResult result )
7497{
7598 VALUE cPgQuery , cParseError ;
@@ -182,6 +205,83 @@ VALUE pg_query_ruby_deparse_protobuf(VALUE self, VALUE input)
182205 return output ;
183206}
184207
208+ VALUE pg_query_ruby_deparse_protobuf_opts (VALUE self , VALUE input , VALUE pretty_print , VALUE comments , VALUE indent_size , VALUE max_line_length , VALUE trailing_newline , VALUE commas_start_of_line )
209+ {
210+ Check_Type (input , T_STRING );
211+ Check_Type (comments , T_ARRAY );
212+ Check_Type (indent_size , T_FIXNUM );
213+ Check_Type (max_line_length , T_FIXNUM );
214+
215+ VALUE output ;
216+ PgQueryProtobuf pbuf = {0 };
217+ PgQueryDeparseResult result = {0 };
218+ PostgresDeparseOpts deparse_opts = {0 };
219+ deparse_opts .pretty_print = RTEST (pretty_print );
220+ deparse_opts .indent_size = NUM2INT (indent_size );
221+ deparse_opts .max_line_length = NUM2INT (max_line_length );
222+ deparse_opts .trailing_newline = RTEST (trailing_newline );
223+ deparse_opts .commas_start_of_line = RTEST (commas_start_of_line );
224+ deparse_opts .comments = malloc (RARRAY_LEN (comments ) * sizeof (PostgresDeparseComment * ));
225+ deparse_opts .comment_count = RARRAY_LEN (comments );
226+ VALUE * comments_arr = RARRAY_PTR (comments );
227+
228+ for (int i = 0 ; i < RARRAY_LEN (comments ); i ++ )
229+ {
230+ PostgresDeparseComment * comment = malloc (sizeof (PostgresDeparseComment ));
231+ VALUE str_ref = rb_ivar_get (comments_arr [i ], rb_intern ("@str" ));
232+ comment -> match_location = NUM2INT (rb_ivar_get (comments_arr [i ], rb_intern ("@match_location" )));
233+ comment -> newlines_before_comment = NUM2INT (rb_ivar_get (comments_arr [i ], rb_intern ("@newlines_before_comment" )));
234+ comment -> newlines_after_comment = NUM2INT (rb_ivar_get (comments_arr [i ], rb_intern ("@newlines_after_comment" )));
235+ comment -> str = StringValueCStr (str_ref );
236+
237+ deparse_opts .comments [i ] = comment ;
238+ }
239+
240+ pbuf .data = StringValuePtr (input );
241+ pbuf .len = RSTRING_LEN (input );
242+ result = pg_query_deparse_protobuf_opts (pbuf , deparse_opts );
243+
244+ if (result .error ) raise_ruby_deparse_error (result );
245+
246+ output = rb_str_new2 (result .query );
247+
248+ pg_query_free_deparse_result (result );
249+ for (int i = 0 ; i < deparse_opts .comment_count ; i ++ )
250+ free (deparse_opts .comments [i ]);
251+ free (deparse_opts .comments );
252+
253+ return output ;
254+ }
255+
256+ VALUE pg_query_ruby_deparse_comments_for_query (VALUE self , VALUE input )
257+ {
258+ Check_Type (input , T_STRING );
259+
260+ VALUE cPgQuery , cDeparseComment ;
261+
262+ cPgQuery = rb_const_get (rb_cObject , rb_intern ("PgQuery" ));
263+ cDeparseComment = rb_const_get_at (cPgQuery , rb_intern ("DeparseComment" ));
264+
265+ VALUE output = rb_ary_new ();
266+ PgQueryDeparseCommentsResult result = pg_query_deparse_comments_for_query (StringValueCStr (input ));
267+ if (result .error ) raise_ruby_deparse_comments_error (result );
268+
269+ for (int i = 0 ; i < result .comment_count ; i ++ )
270+ {
271+ PostgresDeparseComment * comment = result .comments [i ];
272+ VALUE c = rb_class_new_instance (0 , NULL , cDeparseComment );
273+ rb_ivar_set (c , rb_intern ("@str" ), rb_str_new2 (comment -> str ));
274+ rb_ivar_set (c , rb_intern ("@match_location" ), INT2NUM (comment -> match_location ));
275+ rb_ivar_set (c , rb_intern ("@newlines_before_comment" ), INT2NUM (comment -> newlines_before_comment ));
276+ rb_ivar_set (c , rb_intern ("@newlines_after_comment" ), INT2NUM (comment -> newlines_after_comment ));
277+ rb_ary_push (output , c );
278+ }
279+
280+ pg_query_free_deparse_comments_result (result );
281+
282+ return output ;
283+ }
284+
185285VALUE pg_query_ruby_normalize (VALUE self , VALUE input )
186286{
187287 Check_Type (input , T_STRING );
0 commit comments