prestogres 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  /*