docs: public static Procedure compileDefaultProcedure(PlannerTool plannerTool, Procedure catProc, String sqlText) {
          // fake db makes it easy to create procedures that aren't part of the main catalog
          Database fakeDb = new Catalog().getClusters().add("cluster").getDatabases().add("database");
  
          Table table = catProc.getPartitiontable();
  
          // determine the type of the query
          QueryType qtype = QueryType.getFromSQL(sqlText);
  
          StatementPartitioning partitioning =
                  catProc.getSinglepartition() ? StatementPartitioning.forceSP() :
                                                 StatementPartitioning.forceMP();
  
          CompiledPlan plan = plannerTool.planSqlCore(sqlText, partitioning);
  
  
          Procedure newCatProc = fakeDb.getProcedures().add(catProc.getTypeName());
          newCatProc.setClassname(catProc.getClassname());
          newCatProc.setDefaultproc(true);
          newCatProc.setEverysite(false);
          newCatProc.setHasjava(false);
          newCatProc.setPartitioncolumn(catProc.getPartitioncolumn());
          newCatProc.setPartitionparameter(catProc.getPartitionparameter());
          newCatProc.setPartitiontable(catProc.getPartitiontable());
          newCatProc.setReadonly(catProc.getReadonly());
          newCatProc.setSinglepartition(catProc.getSinglepartition());
          newCatProc.setSystemproc(false);
  
          if (catProc.getPartitionparameter() >= 0) {
              newCatProc.setAttachment(
                      new ProcedurePartitionInfo(
                              VoltType.get((byte) catProc.getPartitioncolumn().getType()),
                              catProc.getPartitionparameter()));
          }
  
          CatalogMap<Statement> statements = newCatProc.getStatements();
          assert(statements != null);
  
          /* since there can be multiple statements in a procedure,
           * we name the statements starting from 'sql0' even for single statement procedures
           * since we reuse the same code for single and multi-statement procedures
           *     statements of all single statement procedures are named 'sql0'
          */
          Statement stmt = statements.add(VoltDB.ANON_STMT_NAME + "0");
          stmt.setSqltext(sqlText);
          stmt.setReadonly(catProc.getReadonly());
          stmt.setQuerytype(qtype.getValue());
          stmt.setSinglepartition(catProc.getSinglepartition());
          stmt.setIscontentdeterministic(true);
          stmt.setIsorderdeterministic(true);
          stmt.setNondeterminismdetail("NO CONTENT FOR DEFAULT PROCS");
          stmt.setSeqscancount(plan.countSeqScans());
          stmt.setReplicatedtabledml(!catProc.getReadonly() && table.getIsreplicated());
  
          // Input Parameters
          // We will need to update the system catalogs with this new information
          for (int i = 0; i < plan.getParameters().length; ++i) {
              StmtParameter catalogParam = stmt.getParameters().add(String.valueOf(i));
              catalogParam.setIndex(i);
              ParameterValueExpression pve = plan.getParameters()[i];
              catalogParam.setJavatype(pve.getValueType().getValue());
              catalogParam.setIsarray(pve.getParamIsVector());
          }
  
          PlanFragment frag = stmt.getFragments().add("0");
  
          // compute a hash of the plan
          MessageDigest md = null;
          try {
              md = MessageDigest.getInstance("SHA-1");
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
              assert(false);
              System.exit(-1); // should never happen with healthy jvm
          }
  
          byte[] planBytes = writePlanBytes(frag, plan.rootPlanGraph);
          md.update(planBytes, 0, planBytes.length);
          // compute the 40 bytes of hex from the 20 byte sha1 hash of the plans
          md.reset();
          md.update(planBytes);
          frag.setPlanhash(Encoder.hexEncode(md.digest()));
  
          if (plan.subPlanGraph != null) {
              frag.setHasdependencies(true);
              frag.setNontransactional(true);
              frag.setMultipartition(true);
  
              frag = stmt.getFragments().add("1");
              frag.setHasdependencies(false);
              frag.setNontransactional(false);
              frag.setMultipartition(true);
              byte[] subBytes = writePlanBytes(frag, plan.subPlanGraph);
              // compute the 40 bytes of hex from the 20 byte sha1 hash of the plans
              md.reset();
              md.update(subBytes);
              frag.setPlanhash(Encoder.hexEncode(md.digest()));
          }
          else {
              frag.setHasdependencies(false);
              frag.setNontransactional(false);
              frag.setMultipartition(false);
          }
  
          // set the procedure parameter types from the statement parameter types
          int paramCount = 0;
          for (StmtParameter stmtParam : CatalogUtil.getSortedCatalogItems(stmt.getParameters(), "index")) {
              // name each parameter "param1", "param2", etc...
              ProcParameter procParam = newCatProc.getParameters().add("param" + String.valueOf(paramCount));
              procParam.setIndex(stmtParam.getIndex());
              procParam.setIsarray(stmtParam.getIsarray());
              procParam.setType(stmtParam.getJavatype());
              paramCount++;
          }
  
          return newCatProc;
      }