cql_noexport void cg_query_plan_main()

in sources/cg_query_plan.c [507:647]


cql_noexport void cg_query_plan_main(ast_node *head) {
  sql_stmt_count = 0; // reset statics

  Contract(options.file_names_count == 1);
  cql_exit_on_semantic_errors(head);
  exit_on_validating_schema();

  cg_stmts = symtab_new();

  STMT_INIT(create_proc_stmt);

  // schema
  //  * note probably need to add declare select function to this list
  //    that can be needed to correctly parse the body of triggers or views (which might use the function)
  STMT_INIT_DDL(create_table_stmt);
  STMT_INIT_DDL(create_index_stmt);
  STMT_INIT_DDL(create_view_stmt);
  STMT_INIT_DDL(create_trigger_stmt);

  // dml
  STMT_INIT_EXPL(select_stmt);
  STMT_INIT_EXPL(with_select_stmt);
  STMT_INIT_EXPL(with_insert_stmt);
  STMT_INIT_EXPL(update_stmt);
  STMT_INIT_EXPL(delete_stmt);
  STMT_INIT_EXPL(with_delete_stmt);
  STMT_INIT_EXPL(insert_stmt);
  STMT_INIT_EXPL(upsert_stmt);
  STMT_INIT_EXPL(drop_table_stmt);
  STMT_INIT_EXPL(drop_view_stmt);
  STMT_INIT_EXPL(drop_index_stmt);
  STMT_INIT_EXPL(begin_trans_stmt);
  STMT_INIT_EXPL(commit_trans_stmt);

  CHARBUF_OPEN(query_plans_buf);
  query_plans = &query_plans_buf;
  CHARBUF_OPEN(schema_stmts_buf);
  schema_stmts = &schema_stmts_buf;
  CHARBUF_OPEN(output_buf);

  bprintf(&output_buf, "DECLARE PROC printf NO CHECK;\n");

  gen_sql_callbacks callbacks;
  init_gen_sql_callbacks(&callbacks);
  callbacks.mode = gen_mode_no_annotations;
  callbacks.variables_callback = &variables_callback;
  cg_qp_callbacks = &callbacks;

  cg_qp_stmt_list(head);

  if (sql_stmt_count) {
    bprintf(&output_buf, rt->source_prefix);
    if (options.test) {
      while (head->right) {
        head = head->right;
      }
      bprintf(&output_buf, "-- The statement ending at line %d\n\n", head->left->lineno);
    }
    cg_qp_emit_declare_func(&output_buf);
    bprintf(&output_buf, "\n");
    cg_qp_emit_create_schema_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_populate_no_table_scan_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_populate_tables_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_populate_table_scan_alert_table_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_populate_b_tree_alert_table_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_print_query_violation_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_print_sql_statement_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_print_query_plan_stat_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_print_query_plan_graph_proc(&output_buf);
    bprintf(&output_buf, "\n");
    emit_print_query_plan(&output_buf);
    bprintf(&output_buf, "\n");
  }

  // create an empty query_plan method even if there are no statements
  // (the helpers above won't be needed)
  bprintf(&output_buf, "CREATE PROC query_plan()\n");
  bprintf(&output_buf, "BEGIN\n");
  if (sql_stmt_count) {
    bprintf(&output_buf, "  CALL create_schema();\n");
    bprintf(&output_buf, "  BEGIN TRY\n");
    bprintf(&output_buf, "    CALL populate_no_table_scan();\n");
    bprintf(&output_buf, "  END TRY;\n");
    bprintf(&output_buf, "  BEGIN CATCH\n");
    bprintf(&output_buf, "    CALL printf(\"failed populating no_table_scan table\\n\");\n");
    bprintf(&output_buf, "    THROW;\n");
    bprintf(&output_buf, "  END CATCH;\n");
  }
  for (int32_t i = 1; i <= sql_stmt_count; i++) {
    bprintf(&output_buf, "  BEGIN TRY\n");
    bprintf(&output_buf, "    CALL populate_query_plan_%d();\n", i);
    bprintf(&output_buf, "  END TRY;\n");
    bprintf(&output_buf, "  BEGIN CATCH\n");
    bprintf(&output_buf, "    CALL printf(\"failed populating query %d\\n\");\n", i);
    bprintf(&output_buf, "    THROW;\n");
    bprintf(&output_buf, "  END CATCH;\n");
  }

  bprintf(&output_buf, "  CALL printf(\"[\\n\");\n");

  if (sql_stmt_count) {
    bprintf(&output_buf, "  CALL print_query_violation();\n");
  }

  bprintf(&output_buf, "  CALL printf(\"[\\n\");\n");
  bprintf(&output_buf, "  CALL printf(\"[\\n\");\n");
  bprintf(&output_buf, "  CALL printf(\"[\\\"Query\\\", \\\"Stat\\\", \\\"Graph\\\"],\\n\");\n");
  for (int32_t i = 1; i <= sql_stmt_count; i++) {
    bprintf(&output_buf, "  CALL print_query_plan(%d);\n", i);
  }
  bprintf(&output_buf, "  CALL printf(\"[]\\n\");\n");
  bprintf(&output_buf, "  CALL printf(\"]\\n\");\n");
  bprintf(&output_buf, "  CALL printf(\"],\\n\");\n");

  bprintf(&output_buf, "  CALL printf(\"[]\\n\");\n");
  bprintf(&output_buf, "  CALL printf(\"]\");\n");

  bprintf(&output_buf, "END;\n");

  cql_write_file(options.file_names[0], output_buf.ptr);

  CHARBUF_CLOSE(output_buf);
  CHARBUF_CLOSE(schema_stmts_buf);
  CHARBUF_CLOSE(query_plans_buf);

  // Force the globals to null state so that they do not look like roots to LeakSanitizer
  // all of these should have been freed already.  This is the final safety net to prevent
  // non-reporting of leaks.

  schema_stmts = NULL;
  query_plans = NULL;
  cg_qp_callbacks = NULL;
}