static void _ringoIndexStart (OracleEnv &env, RingoFetchContext &context,
                              const char *oper, const Array<char> &query_buf,
                              OCINumber *p_strt, OCINumber *p_stop, const char *params)
{
   RingoShadowFetch &shadow_fetch = context.shadow_fetch.ref();
   RingoFastIndex   &fast_index   = context.fast_index.ref();

   if (strcasecmp(oper, "RSUB") == 0)
   {
      if (!context.substructure.parse(params))
         throw BingoError("can not parse parameters: %s", params);
      
      context.substructure.loadQuery(query_buf);

      int right = bingoGetExactRightPart(env, p_strt, p_stop, 64);

      if (right == 1)
      {
         fast_index.prepareSubstructure(env);
         context.fetch_engine = &fast_index;
      }
      else // right == 0
      {
         shadow_fetch.prepareNonSubstructure(env);
         context.fetch_engine = &shadow_fetch;
      }
   }
   else if (strcasecmp(oper, "RSMARTS") == 0)
   {
      context.substructure.loadSMARTS(query_buf);

      int right = bingoGetExactRightPart(env, p_strt, p_stop, 64);

      if (right == 1)
      {
         fast_index.prepareSubstructure(env);
         context.fetch_engine = &fast_index;
      }
      else // right == 0
      {
         shadow_fetch.prepareNonSubstructure(env);
         context.fetch_engine = &shadow_fetch;
      }
   }
   else if (strcasecmp(oper, "REXACT") == 0)
   {
      context.exact.setParameters(params);
      context.exact.loadQuery(query_buf);

      int right = bingoGetExactRightPart(env, p_strt, p_stop, 64);

      shadow_fetch.prepareExact(env, right);
      context.fetch_engine = &shadow_fetch;
   }
   else
      throw BingoError("unknown operator: %s", oper);
}
static void _mangoIndexStart (OracleEnv &env, MangoFetchContext &context,
                              const char *oper, const Array<char> &query_buf,
                              OCINumber *p_strt, OCINumber *p_stop,
                              int flags, const char *params)
{
    MangoShadowFetch &shadow_fetch = context.shadow_fetch.ref();
    MangoFastIndex   &fast_index   = context.fast_index.ref();

    if (strcasecmp(oper, "SUB") == 0)
    {
        if (context.substructure.parse(params))
        {
            context.substructure.loadQuery(query_buf);

            int right = bingoGetExactRightPart(env, p_strt, p_stop, flags);

            if (right == 1)
            {
                fast_index.prepareSubstructure(env);
                context.fetch_engine = &fast_index;
            }
            else // right == 0
            {
                shadow_fetch.prepareNonSubstructure(env);
                context.fetch_engine = &shadow_fetch;
            }
        }
        else if (context.tautomer.parseSub(params))
        {
            context.tautomer.loadQuery(query_buf);

            int right = bingoGetExactRightPart(env, p_strt, p_stop, flags);

            if (right == 1)
            {
                fast_index.prepareTautomerSubstructure(env);
                context.fetch_engine = &fast_index;
            }
            else // right == 0
            {
                shadow_fetch.prepareNonTautomerSubstructure(env);
                context.fetch_engine = &shadow_fetch;
            }
        }
        else
            throw BingoError("can't parse parameters: '%s'", params);
    }
    else if (strcasecmp(oper, "SMARTS") == 0)
    {
        context.substructure.loadSMARTS(query_buf);

        int right = bingoGetExactRightPart(env, p_strt, p_stop, flags);

        if (right == 1)
        {
            fast_index.prepareSubstructure(env);
            context.fetch_engine = &fast_index;
        }
        else // right == 0
        {
            shadow_fetch.prepareNonSubstructure(env);
            context.fetch_engine = &shadow_fetch;
        }
    }
    else if (strcasecmp(oper, "EXACT") == 0)
    {
        if (context.tautomer.parseExact(params))
        {
            context.tautomer.loadQuery(query_buf);

            int right = bingoGetExactRightPart(env, p_strt, p_stop, flags);

            shadow_fetch.prepareTautomer(env, right);
            context.fetch_engine = &shadow_fetch;
        }
        else if (context.exact.parse(params))
        {
            context.exact.loadQuery(query_buf);

            int right = bingoGetExactRightPart(env, p_strt, p_stop, flags);

            shadow_fetch.prepareExact(env, right);
            context.fetch_engine = &shadow_fetch;
        }
        else
            throw BingoError("can't parse parameters: '%s'", params);
    }
    else if (strcasecmp(oper, "SIM") == 0)
    {
        context.similarity.setMetrics(params);
        context.similarity.loadQuery(query_buf);

        float bottom = -0.1f;
        float top = 1.1f;

        if (p_strt == 0 && p_stop == 0)
            throw BingoError("no bounds for similarity search");

        if (p_strt != 0)
            bottom = OracleUtil::numberToFloat(env, p_strt);
        if (p_stop != 0)
            top = OracleUtil::numberToFloat(env, p_stop);

        if (flags & 64)
            throw BingoError("exact match not allowed");

        context.similarity.include_bottom = ((flags & 16) != 0);
        context.similarity.include_top = ((flags & 32) != 0);
        context.similarity.bottom = bottom;
        context.similarity.top = top;

        fast_index.prepareSimilarity(env);
        context.fetch_engine = &fast_index;
    }
    else if (strcasecmp(oper, "GROSS") == 0)
    {
        int right = bingoGetExactRightPart(env, p_strt, p_stop, flags);

        MangoGross &instance = context.gross;

        instance.parseQuery(query_buf);

        shadow_fetch.prepareGross(env, right);
        context.fetch_engine = &shadow_fetch;
    }
    else if (strcasecmp(oper, "MASS") == 0)
    {
        float bottom = 0;
        float top = 1e10;

        if (p_strt == 0 && p_stop == 0)
            throw BingoError("no bounds for molecular mass search");

        if (p_strt != 0)
            bottom = OracleUtil::numberToFloat(env, p_strt);
        if (p_stop != 0)
            top = OracleUtil::numberToFloat(env, p_stop);

        context.mass.bottom = bottom;
        context.mass.top = top;

        shadow_fetch.prepareMass(env);
        context.fetch_engine = &shadow_fetch;
    }
    else
        throw BingoError("unknown operator: %s", oper);
}