prestogres 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -896,6 +896,9 @@ POOL_STATUS Parse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
896
896
  POOL_SESSION_CONTEXT *session_context;
897
897
  POOL_QUERY_CONTEXT *query_context;
898
898
 
899
+ pool_error("Parse: Prestogres doesn't support extended query");
900
+ return POOL_END;
901
+
899
902
  /* Get session context */
900
903
  session_context = pool_get_session_context();
901
904
  if (!session_context)
@@ -1031,16 +1034,6 @@ POOL_STATUS Parse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
1031
1034
  */
1032
1035
  pool_where_to_send(query_context, query_context->original_query,
1033
1036
  query_context->parse_tree);
1034
- {
1035
- int alloc_len = len - strlen(stmt) + strlen(query_context->original_query);
1036
- contents = palloc(alloc_len);
1037
- strcpy(contents, name);
1038
- strcpy(contents + strlen(name) + 1, query_context->original_query);
1039
- memcpy(contents + strlen(name) + 1 + strlen(query_context->original_query) + 1,
1040
- stmt + strlen(stmt) + 1,
1041
- len - (strlen(name) + 1 + strlen(stmt) + 1));
1042
- len = alloc_len;
1043
- }
1044
1037
 
1045
1038
  if (REPLICATION)
1046
1039
  {
@@ -289,122 +289,244 @@ int pool_virtual_master_db_node_id(void)
289
289
  return my_master_node_id;
290
290
  }
291
291
 
292
- char rewrite_query_string_buffer[QUERY_STRING_BUFFER_LEN];
293
-
294
292
  #ifndef PRESTO_RESULT_TABLE_NAME
295
293
  #define PRESTO_RESULT_TABLE_NAME "presto_result"
296
294
  #endif
297
295
 
298
- static POOL_STATUS run_clear_query(POOL_SESSION_CONTEXT* session_context, POOL_QUERY_CONTEXT* query_context)
296
+ char rewrite_query_string_buffer[QUERY_STRING_BUFFER_LEN];
297
+
298
+ static char *strcpy_capped(char *buffer, int length, const char *string)
299
299
  {
300
- //POOL_STATUS status;
301
- //POOL_SELECT_RESULT *res;
302
- //POOL_CONNECTION *con;
303
- //POOL_CONNECTION_POOL *backend = session_context->backend;
304
- //con = CONNECTION(backend, session_context->load_balance_node_id);
300
+ int slen;
305
301
 
306
- // do something if multi-statement?
302
+ if (buffer == NULL) {
303
+ return NULL;
304
+ }
307
305
 
308
- return POOL_CONTINUE;
306
+ slen = strlen(string);
307
+ if (length <= slen) {
308
+ return NULL;
309
+ }
310
+
311
+ memcpy(buffer, string, slen + 1);
312
+ return buffer + slen;
309
313
  }
310
314
 
311
- static POOL_STATUS run_system_catalog_query(POOL_SESSION_CONTEXT* session_context, POOL_QUERY_CONTEXT* query_context)
315
+ static char *strcpy_capped_escaped(char *buffer, int length, const char *string, const char *escape_chars)
312
316
  {
313
- POOL_STATUS status;
314
- POOL_SELECT_RESULT *res;
315
- POOL_CONNECTION *con;
316
- POOL_CONNECTION_POOL *backend = session_context->backend;
317
- con = CONNECTION(backend, session_context->load_balance_node_id);
317
+ char *bpos, *bend;
318
+ const char *spos, *send;
319
+ bool escaped = false;
318
320
 
319
- snprintf(rewrite_query_string_buffer, sizeof(rewrite_query_string_buffer),
320
- "select presto_create_tables('%s', '%s', '%s')",
321
- presto_server, presto_user, presto_catalog);
322
- status = do_query(con, rewrite_query_string_buffer, &res, MAJOR(backend));
323
- free_select_result(res);
321
+ if (buffer == NULL) {
322
+ return NULL;
323
+ }
324
324
 
325
- if (status != POOL_CONTINUE) {
326
- // TODO error message
327
- return status;
328
- }
325
+ bpos = buffer;
326
+ bend = buffer + length;
327
+ spos = string;
328
+ send = string + strlen(string);
329
+ while (spos < send) {
330
+ if (bpos >= bend) {
331
+ return NULL;
332
+ }
329
333
 
330
- return POOL_CONTINUE;
331
- }
334
+ if (escaped) {
335
+ *bpos = *spos;
336
+ escaped = false;
337
+ spos++;
338
+ } else if (strchr(escape_chars, *spos) != NULL) {
339
+ *bpos = '\\';
340
+ escaped = true;
341
+ } else {
342
+ *bpos = *spos;
343
+ spos++;
344
+ }
332
345
 
333
- static char* escape_original_query(const char* original_query)
334
- {
335
- char* query;
336
- char* c;
346
+ bpos++;
347
+ }
337
348
 
338
- query = malloc(QUERY_STRING_BUFFER_LEN);
339
- strlcpy(query, original_query, QUERY_STRING_BUFFER_LEN);
349
+ if (bpos >= bend) {
350
+ return NULL;
351
+ }
352
+ *bpos = '\0';
340
353
 
341
- // remove last ;
342
- c = strrchr(query, ';');
343
- if (c != NULL) {
344
- *c = '\0';
345
- }
354
+ return bpos;
355
+ }
346
356
 
347
- // TODO escape ' character
357
+ static void do_replace_query(POOL_QUERY_CONTEXT* query_context, const char *query)
358
+ {
359
+ char *dupq = pstrdup(query);
348
360
 
349
- return query;
361
+ query_context->original_query = dupq;
362
+ query_context->original_length = strlen(dupq) + 1;
350
363
  }
351
364
 
352
- static POOL_STATUS run_presto_query(POOL_SESSION_CONTEXT* session_context, POOL_QUERY_CONTEXT* query_context)
365
+ static void rewrite_error_query(POOL_QUERY_CONTEXT* query_context, const char *message, const char* errcode)
353
366
  {
354
- POOL_STATUS status;
355
- POOL_SELECT_RESULT *res;
356
- POOL_CONNECTION *con;
357
- POOL_CONNECTION_POOL *backend = session_context->backend;
358
- con = CONNECTION(backend, session_context->load_balance_node_id);
359
- char* query;
360
-
361
- snprintf(rewrite_query_string_buffer, sizeof(rewrite_query_string_buffer),
362
- "drop table if exists %s",
363
- PRESTO_RESULT_TABLE_NAME);
364
- status = do_query(con, rewrite_query_string_buffer, &res, MAJOR(backend));
365
- free_select_result(res);
366
-
367
- if (status != POOL_CONTINUE) {
368
- // TODO error message
369
- return status;
370
- }
371
-
372
- query = escape_original_query(query_context->original_query);
373
- snprintf(rewrite_query_string_buffer, sizeof(rewrite_query_string_buffer),
374
- "select run_presto_as_temp_table('%s', '%s', '%s', '%s', '%s', '%s')",
375
- presto_server, presto_user, presto_catalog, presto_schema,
376
- PRESTO_RESULT_TABLE_NAME, query);
377
- free(query);
378
-
379
- status = do_query(con, rewrite_query_string_buffer, &res, MAJOR(backend));
380
- free_select_result(res);
381
-
382
- if (status != POOL_CONTINUE) {
383
- // TODO error message
384
- return status;
385
- }
367
+ char *buffer, *bufend;
368
+
369
+ buffer = rewrite_query_string_buffer;
370
+ bufend = buffer + sizeof(rewrite_query_string_buffer);
371
+
372
+ buffer = strcpy_capped(buffer, bufend - buffer, "do $$ begin raise ");
373
+ buffer = strcpy_capped(buffer, bufend - buffer, "exception '%', E'");
374
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, message, "'\\$");
375
+ buffer = strcpy_capped(buffer, bufend - buffer, "'");
376
+ if (errcode != NULL) {
377
+ buffer = strcpy_capped(buffer, bufend - buffer, " using errcode = E'");
378
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, errcode, "'\\$");
379
+ buffer = strcpy_capped(buffer, bufend - buffer, "'");
380
+ }
381
+ buffer = strcpy_capped(buffer, bufend - buffer, "; end $$ language plpgsql");
386
382
 
387
- return POOL_CONTINUE;
383
+ if (buffer == NULL) {
384
+ do_replace_query(query_context,
385
+ "do $$ begin raise ecxeption 'too long error message'; end $$ language plpgsql");
386
+ return;
387
+ }
388
+
389
+ do_replace_query(query_context, rewrite_query_string_buffer);
388
390
  }
389
391
 
390
- static void do_replace_query(POOL_QUERY_CONTEXT* query_context, const char* query)
392
+ static void run_clear_query(POOL_SESSION_CONTEXT* session_context, POOL_QUERY_CONTEXT* query_context)
391
393
  {
392
- char* dupq = pstrdup(query);
393
-
394
- query_context->original_query = dupq;
395
- query_context->original_length = strlen(dupq) + 1;
394
+ // TODO
396
395
  }
397
396
 
398
- static void rewrite_presto_query(POOL_QUERY_CONTEXT* query_context)
397
+ static void run_and_rewrite_system_catalog_query(POOL_SESSION_CONTEXT* session_context, POOL_QUERY_CONTEXT* query_context)
399
398
  {
400
- snprintf(rewrite_query_string_buffer, sizeof(rewrite_query_string_buffer),
401
- "select * from %s", PRESTO_RESULT_TABLE_NAME);
402
- do_replace_query(query_context, rewrite_query_string_buffer);
399
+ char *buffer, *bufend;
400
+ char *errmsg = NULL, *errcode = NULL;
401
+ POOL_STATUS status;
402
+ POOL_SELECT_RESULT *res;
403
+ POOL_CONNECTION *con;
404
+ POOL_CONNECTION_POOL *backend = session_context->backend;
405
+ con = CONNECTION(backend, session_context->load_balance_node_id);
406
+
407
+ /* build query */
408
+ buffer = rewrite_query_string_buffer;
409
+ bufend = buffer + sizeof(rewrite_query_string_buffer);
410
+
411
+ buffer = strcpy_capped(buffer, bufend - buffer, "select prestogres_catalog.run_system_catalog_as_temp_table(E'");
412
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, presto_server, "'\\");
413
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
414
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, presto_user, "'\\");
415
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
416
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, presto_catalog, "'\\");
417
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
418
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, PRESTO_RESULT_TABLE_NAME, "'\\");
419
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
420
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, query_context->original_query, "'\\");
421
+ buffer = strcpy_capped(buffer, bufend - buffer, "')");
422
+
423
+ if (buffer == NULL) {
424
+ rewrite_error_query(query_context, "metadata too long", NULL);
425
+ return;
426
+ }
427
+
428
+ /* run query */
429
+ status = do_query_or_get_error_message(con,
430
+ rewrite_query_string_buffer, &res, MAJOR(backend), &errmsg, &errcode);
431
+ free_select_result(res);
432
+
433
+ if (errmsg != NULL) {
434
+ rewrite_error_query(query_context, errmsg, errcode);
435
+ } else if (status != POOL_CONTINUE) {
436
+ rewrite_error_query(query_context, "Unknown execution error", NULL);
437
+ }
438
+
439
+ /* rewrite query */
440
+ buffer = rewrite_query_string_buffer;
441
+ bufend = buffer + sizeof(rewrite_query_string_buffer);
442
+
443
+ buffer = strcpy_capped(buffer, bufend - buffer, "select * from ");
444
+ buffer = strcpy_capped(buffer, bufend - buffer, PRESTO_RESULT_TABLE_NAME);
445
+
446
+ if (buffer == NULL) {
447
+ rewrite_error_query(query_context, "query too long", NULL);
448
+ return;
449
+ }
450
+
451
+ do_replace_query(query_context, rewrite_query_string_buffer);
403
452
  }
404
453
 
405
- static void rewrite_error_query(POOL_QUERY_CONTEXT* query_context, const char* message)
454
+ static void run_and_rewrite_presto_query(POOL_SESSION_CONTEXT* session_context, POOL_QUERY_CONTEXT* query_context)
406
455
  {
407
- // TODO
456
+ char *buffer, *bufend;
457
+ char *errmsg = NULL, *errcode = NULL;
458
+ POOL_STATUS status;
459
+ POOL_SELECT_RESULT *res;
460
+ POOL_CONNECTION *con;
461
+ POOL_CONNECTION_POOL *backend = session_context->backend;
462
+ con = CONNECTION(backend, session_context->load_balance_node_id);
463
+
464
+ /* build query */
465
+ buffer = rewrite_query_string_buffer;
466
+ bufend = buffer + sizeof(rewrite_query_string_buffer);
467
+
468
+ buffer = strcpy_capped(buffer, bufend - buffer, "select prestogres_catalog.run_presto_as_temp_table(E'");
469
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, presto_server, "'\\");
470
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
471
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, presto_user, "'\\");
472
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
473
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, presto_catalog, "'\\");
474
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
475
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, presto_schema, "'\\");
476
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
477
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, PRESTO_RESULT_TABLE_NAME, "'\\");
478
+ buffer = strcpy_capped(buffer, bufend - buffer, "', E'");
479
+ {
480
+ char *query = query_context->original_query;
481
+ char *c = strrchr(query, ';');
482
+ int save;
483
+
484
+ // remove last ';'
485
+ if (c != NULL) {
486
+ save = *c;
487
+ *c = '\0';
488
+ }
489
+
490
+ buffer = strcpy_capped_escaped(buffer, bufend - buffer, query, "'\\");
491
+
492
+ // restore last ';'
493
+ if (c != NULL) {
494
+ *c = save;
495
+ }
496
+ }
497
+ buffer = strcpy_capped(buffer, bufend - buffer, "')");
498
+
499
+ if (buffer == NULL) {
500
+ rewrite_error_query(query_context, "query too long", NULL);
501
+ return;
502
+ }
503
+
504
+ /* run query */
505
+ status = do_query_or_get_error_message(con,
506
+ rewrite_query_string_buffer, &res, MAJOR(backend), &errmsg, &errcode);
507
+ free_select_result(res);
508
+
509
+ if (errmsg != NULL) {
510
+ rewrite_error_query(query_context, errmsg, errcode);
511
+ return;
512
+ } else if (status != POOL_CONTINUE) {
513
+ rewrite_error_query(query_context, "Unknown execution error", NULL);
514
+ return;
515
+ }
516
+
517
+ /* rewrite query */
518
+ buffer = rewrite_query_string_buffer;
519
+ bufend = buffer + sizeof(rewrite_query_string_buffer);
520
+
521
+ buffer = strcpy_capped(buffer, bufend - buffer, "select * from ");
522
+ buffer = strcpy_capped(buffer, bufend - buffer, PRESTO_RESULT_TABLE_NAME);
523
+
524
+ if (buffer == NULL) {
525
+ rewrite_error_query(query_context, "query too long", NULL);
526
+ return;
527
+ }
528
+
529
+ do_replace_query(query_context, rewrite_query_string_buffer);
408
530
  }
409
531
 
410
532
  /*
@@ -416,7 +538,6 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
416
538
  POOL_CONNECTION_POOL *backend;
417
539
  int i;
418
540
 
419
- POOL_STATUS status;
420
541
  const char* rewrite_error_message;
421
542
  enum {
422
543
  REWRITE_CLEAR,
@@ -502,13 +623,13 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
502
623
  /* Should be sent to primary only? */
503
624
  if (dest == POOL_PRIMARY)
504
625
  {
505
- pool_debug("pggw: send_to_where: POOL_PRIMARY\n");
626
+ pool_debug("prestogres: send_to_where: POOL_PRIMARY");
506
627
  pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
507
628
  }
508
629
  /* Should be sent to both primary and standby? */
509
630
  else if (dest == POOL_BOTH)
510
631
  {
511
- pool_debug("pggw: send_to_where: POOL_BOTH\n");
632
+ pool_debug("prestogres: send_to_where: POOL_BOTH");
512
633
  pool_setall_node_to_be_sent(query_context);
513
634
  }
514
635
 
@@ -545,7 +666,7 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
545
666
  pool_config->delay_threshold &&
546
667
  bkinfo->standby_delay > pool_config->delay_threshold)
547
668
  {
548
- pool_debug("pggw: send_to_where: replication delay\n");
669
+ pool_debug("prestogres: send_to_where: replication delay");
549
670
  pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
550
671
  rewrite_mode = REWRITE_ERROR;
551
672
  rewrite_error_message = "unexpected replication delay";
@@ -557,7 +678,7 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
557
678
  */
558
679
  else if (pool_has_function_call(node))
559
680
  {
560
- pool_debug("pggw: send_to_where: writing function\n");
681
+ pool_debug("prestogres: send_to_where: writing function");
561
682
  pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
562
683
  }
563
684
 
@@ -575,7 +696,7 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
575
696
  */
576
697
  else if (pool_has_system_catalog(node))
577
698
  {
578
- pool_debug("pggw: send_to_where: system catalog\n");
699
+ pool_debug("prestogres: send_to_where: system catalog");
579
700
  pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
580
701
  rewrite_mode = REWRITE_SYSTEM_CATALOG;
581
702
  }
@@ -586,7 +707,7 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
586
707
  */
587
708
  else if (pool_config->check_temp_table && pool_has_temp_table(node))
588
709
  {
589
- pool_debug("pggw: send_to_where: temporary table\n");
710
+ pool_debug("prestogres: send_to_where: temporary table");
590
711
  pool_set_node_to_be_sent(query_context,
591
712
  session_context->load_balance_node_id);
592
713
  rewrite_mode = REWRITE_PRESTO;
@@ -598,7 +719,7 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
598
719
  */
599
720
  else if (pool_has_unlogged_table(node))
600
721
  {
601
- pool_debug("pggw: send_to_where: unlogged table\n");
722
+ pool_debug("prestogres: send_to_where: unlogged table");
602
723
  pool_set_node_to_be_sent(query_context,
603
724
  session_context->load_balance_node_id);
604
725
  rewrite_mode = REWRITE_PRESTO;
@@ -610,14 +731,14 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
610
731
  */
611
732
  else if (!pool_has_relation(node))
612
733
  {
613
- pool_debug("pggw: send_to_where: no relation\n");
734
+ pool_debug("prestogres: send_to_where: no relation");
614
735
  pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
615
736
  rewrite_mode = REWRITE_SYSTEM_CATALOG;
616
737
  }
617
738
 
618
739
  else
619
740
  {
620
- pool_debug("pggw: send_to_where: load balance\n");
741
+ pool_debug("prestogres: send_to_where: load balance");
621
742
  pool_set_node_to_be_sent(query_context,
622
743
  session_context->load_balance_node_id);
623
744
  rewrite_mode = REWRITE_PRESTO;
@@ -626,7 +747,7 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
626
747
  else
627
748
  {
628
749
  /* Send to the primary only */
629
- pool_debug("pggw: send_to_where: invalid session state\n");
750
+ pool_debug("prestogres: send_to_where: invalid session state");
630
751
  pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
631
752
  rewrite_mode = REWRITE_ERROR;
632
753
  rewrite_error_message = "invalid session state";
@@ -635,7 +756,7 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
635
756
  else
636
757
  {
637
758
  /* Send to the primary only */
638
- pool_debug("pggw: send_to_where: non-select\n");
759
+ pool_debug("prestogres: send_to_where: non-select");
639
760
  pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
640
761
  rewrite_mode = REWRITE_ERROR;
641
762
  rewrite_error_message = "only SELECT is supported";
@@ -732,32 +853,21 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
732
853
 
733
854
  switch (rewrite_mode) {
734
855
  case REWRITE_CLEAR:
735
- status = run_clear_query(session_context, query_context);
856
+ run_clear_query(session_context, query_context);
736
857
  break;
737
858
 
738
859
  case REWRITE_SYSTEM_CATALOG:
739
- status = run_system_catalog_query(session_context, query_context);
860
+ run_and_rewrite_system_catalog_query(session_context, query_context);
740
861
  break;
741
862
 
742
863
  case REWRITE_PRESTO:
743
- status = run_presto_query(session_context, query_context);
744
- rewrite_presto_query(query_context);
864
+ run_and_rewrite_presto_query(session_context, query_context);
745
865
  break;
746
866
 
747
867
  case REWRITE_ERROR:
748
- rewrite_error_query(query_context, rewrite_error_message);
749
- status = POOL_CONTINUE;
868
+ rewrite_error_query(query_context, rewrite_error_message, NULL);
750
869
  break;
751
870
  }
752
-
753
- if (status != POOL_CONTINUE) {
754
- pool_error("presto-pggw: query failed");
755
- return;
756
- }
757
-
758
- pool_debug("exec status: %d POOL_CONTINUE=%d\n", status, POOL_CONTINUE);
759
-
760
- return;
761
871
  }
762
872
 
763
873
  /*