Skip to content

Commit 40cbcd2

Browse files
committed
Add INSERT/REPLACE deep parser with emitter and classifier integration
InsertParser<D> handles full MySQL and PostgreSQL INSERT/REPLACE syntax: - MySQL: INSERT/REPLACE [LOW_PRIORITY|DELAYED|HIGH_PRIORITY] [IGNORE] [INTO] table [(cols)] {VALUES|SELECT|SET} [ON DUPLICATE KEY UPDATE] - PostgreSQL: INSERT INTO table [(cols)] {VALUES|SELECT|DEFAULT VALUES} [ON CONFLICT ...] [RETURNING ...] Emitter extended with all INSERT-related node types. Classifier updated to route TK_INSERT and TK_REPLACE to parse_insert(). Backward compatibility maintained for table_name/schema_name extraction.
1 parent 85eaaf6 commit 40cbcd2

4 files changed

Lines changed: 687 additions & 3 deletions

File tree

include/sql_parser/emitter.h

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,20 @@ class Emitter {
5454
case NodeType::NODE_LOCKING_CLAUSE: emit_locking(node); break;
5555
case NodeType::NODE_INTO_CLAUSE: emit_into(node); break;
5656

57+
// ---- INSERT statement ----
58+
case NodeType::NODE_INSERT_STMT: emit_insert_stmt(node); break;
59+
case NodeType::NODE_INSERT_COLUMNS: emit_insert_columns(node); break;
60+
case NodeType::NODE_VALUES_CLAUSE: emit_values_clause(node); break;
61+
case NodeType::NODE_VALUES_ROW: emit_values_row(node); break;
62+
case NodeType::NODE_INSERT_SET_CLAUSE: emit_insert_set_clause(node); break;
63+
case NodeType::NODE_ON_DUPLICATE_KEY: emit_on_duplicate_key(node); break;
64+
case NodeType::NODE_ON_CONFLICT: emit_on_conflict(node); break;
65+
case NodeType::NODE_CONFLICT_TARGET: emit_conflict_target(node); break;
66+
case NodeType::NODE_CONFLICT_ACTION: emit_conflict_action(node); break;
67+
case NodeType::NODE_RETURNING_CLAUSE: emit_returning(node); break;
68+
case NodeType::NODE_STMT_OPTIONS: emit_stmt_options(node); break;
69+
case NodeType::NODE_UPDATE_SET_ITEM: emit_update_set_item(node); break;
70+
5771
// ---- Table references ----
5872
case NodeType::NODE_TABLE_REF: emit_table_ref(node); break;
5973
case NodeType::NODE_ALIAS: emit_alias(node); break;
@@ -380,6 +394,197 @@ class Emitter {
380394
}
381395
}
382396

397+
// ---- INSERT ----
398+
399+
void emit_insert_stmt(const AstNode* node) {
400+
// Check FLAG_REPLACE
401+
if (node->flags & 0x01) {
402+
sb_.append("REPLACE");
403+
} else {
404+
sb_.append("INSERT");
405+
}
406+
407+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
408+
switch (child->type) {
409+
case NodeType::NODE_STMT_OPTIONS:
410+
sb_.append_char(' ');
411+
emit_node(child);
412+
break;
413+
case NodeType::NODE_TABLE_REF:
414+
sb_.append(" INTO ");
415+
emit_node(child);
416+
break;
417+
case NodeType::NODE_INSERT_COLUMNS:
418+
sb_.append_char(' ');
419+
emit_node(child);
420+
break;
421+
case NodeType::NODE_VALUES_CLAUSE:
422+
sb_.append_char(' ');
423+
emit_node(child);
424+
break;
425+
case NodeType::NODE_SELECT_STMT:
426+
sb_.append_char(' ');
427+
emit_node(child);
428+
break;
429+
case NodeType::NODE_INSERT_SET_CLAUSE:
430+
sb_.append_char(' ');
431+
emit_node(child);
432+
break;
433+
case NodeType::NODE_ON_DUPLICATE_KEY:
434+
sb_.append_char(' ');
435+
emit_node(child);
436+
break;
437+
case NodeType::NODE_ON_CONFLICT:
438+
sb_.append_char(' ');
439+
emit_node(child);
440+
break;
441+
case NodeType::NODE_RETURNING_CLAUSE:
442+
sb_.append_char(' ');
443+
emit_node(child);
444+
break;
445+
default:
446+
sb_.append_char(' ');
447+
emit_node(child);
448+
break;
449+
}
450+
}
451+
}
452+
453+
void emit_stmt_options(const AstNode* node) {
454+
bool first = true;
455+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
456+
if (!first) sb_.append_char(' ');
457+
first = false;
458+
emit_node(child);
459+
}
460+
}
461+
462+
void emit_insert_columns(const AstNode* node) {
463+
sb_.append_char('(');
464+
bool first = true;
465+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
466+
if (!first) sb_.append(", ");
467+
first = false;
468+
emit_node(child);
469+
}
470+
sb_.append_char(')');
471+
}
472+
473+
void emit_values_clause(const AstNode* node) {
474+
// Check for DEFAULT VALUES (value stored in node)
475+
if (node->value_len > 0) {
476+
emit_value(node); // "DEFAULT VALUES"
477+
return;
478+
}
479+
sb_.append("VALUES ");
480+
bool first = true;
481+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
482+
if (!first) sb_.append(", ");
483+
first = false;
484+
emit_node(child);
485+
}
486+
}
487+
488+
void emit_values_row(const AstNode* node) {
489+
sb_.append_char('(');
490+
bool first = true;
491+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
492+
if (!first) sb_.append(", ");
493+
first = false;
494+
emit_node(child);
495+
}
496+
sb_.append_char(')');
497+
}
498+
499+
void emit_insert_set_clause(const AstNode* node) {
500+
sb_.append("SET ");
501+
bool first = true;
502+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
503+
if (!first) sb_.append(", ");
504+
first = false;
505+
emit_node(child);
506+
}
507+
}
508+
509+
void emit_update_set_item(const AstNode* node) {
510+
const AstNode* col = node->first_child;
511+
const AstNode* val = col ? col->next_sibling : nullptr;
512+
if (col) emit_node(col);
513+
sb_.append(" = ");
514+
if (val) emit_node(val);
515+
}
516+
517+
void emit_on_duplicate_key(const AstNode* node) {
518+
sb_.append("ON DUPLICATE KEY UPDATE ");
519+
bool first = true;
520+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
521+
if (!first) sb_.append(", ");
522+
first = false;
523+
emit_node(child);
524+
}
525+
}
526+
527+
void emit_on_conflict(const AstNode* node) {
528+
sb_.append("ON CONFLICT");
529+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
530+
sb_.append_char(' ');
531+
emit_node(child);
532+
}
533+
}
534+
535+
void emit_conflict_target(const AstNode* node) {
536+
if (node->value_len > 0) {
537+
// ON CONSTRAINT name
538+
emit_value(node); // "ON CONSTRAINT"
539+
sb_.append_char(' ');
540+
if (node->first_child) emit_node(node->first_child);
541+
} else {
542+
// (col1, col2, ...)
543+
sb_.append_char('(');
544+
bool first = true;
545+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
546+
if (!first) sb_.append(", ");
547+
first = false;
548+
emit_node(child);
549+
}
550+
sb_.append_char(')');
551+
}
552+
}
553+
554+
void emit_conflict_action(const AstNode* node) {
555+
sb_.append("DO ");
556+
StringRef action_type{node->value_ptr, node->value_len};
557+
if (action_type.equals_ci("NOTHING", 7)) {
558+
sb_.append("NOTHING");
559+
} else if (action_type.equals_ci("UPDATE", 6)) {
560+
sb_.append("UPDATE SET ");
561+
bool first = true;
562+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
563+
if (child->type == NodeType::NODE_WHERE_CLAUSE) {
564+
emit_node(child);
565+
} else {
566+
if (!first) sb_.append(", ");
567+
first = false;
568+
emit_node(child);
569+
}
570+
}
571+
}
572+
}
573+
574+
void emit_returning(const AstNode* node) {
575+
sb_.append("RETURNING ");
576+
bool first = true;
577+
for (const AstNode* child = node->first_child; child; child = child->next_sibling) {
578+
if (child->type == NodeType::NODE_ALIAS) {
579+
emit_node(child);
580+
} else {
581+
if (!first) sb_.append(", ");
582+
first = false;
583+
emit_node(child);
584+
}
585+
}
586+
}
587+
383588
// ---- Expressions ----
384589

385590
void emit_binary_op(const AstNode* node) {

0 commit comments

Comments
 (0)