BOOL ssps_get_out_params()

in driver/my_prepared_stmt.cc [85:247]


BOOL ssps_get_out_params(STMT *stmt)
{
  /* If we use prepared statement, and the query is CALL and we have any
    user's parameter described as INOUT or OUT and that is only result */
  if (is_call_procedure(&stmt->query))
  {
    MYSQL_ROW values= NULL;
    DESCREC   *iprec, *aprec;
    uint      counter= 0;
    int       i, out_params;

    /*Since OUT parameters can be completely different - we have to free current
      bind and bind new */

    free_result_bind(stmt);
    /* Thus function interface has to be changed */
    if (stmt->ssps_bind_result() == 0)
    {
      try
      {
        values = stmt->fetch_row();
      }
      catch(MYERROR&)
      {
        return FALSE;
      }

      /* We need this for fetch_varlength_columns pointed by fix_fields, so it omits
         streamed parameters */
      out_params= got_out_parameters(stmt);

      if (out_params & GOT_OUT_STREAM_PARAMETERS)
      {
        stmt->out_params_state= OPS_STREAMS_PENDING;
        stmt->current_param= ~0L;
        stmt->reset_getdata_position();
      }
      else//(out_params & GOT_OUT_PARAMETERS)
      {
        stmt->out_params_state= OPS_PREFETCHED;
      }

      if (stmt->fix_fields)
      {
        values= (*stmt->fix_fields)(stmt,values);
      }
    }

    assert(values);

    if (values)
    {
      stmt->current_values= values;

      if (out_params)
      {
        for (i= 0;
             i < myodbc_min(stmt->ipd->rcount(), stmt->apd->rcount()) && counter < stmt->field_count();
             ++i)
        {
          /* Making bit field look "normally" */
          if (stmt->result_bind[counter].buffer_type == MYSQL_TYPE_BIT)
          {
            MYSQL_FIELD *field= mysql_fetch_field_direct(stmt->result, counter);
            unsigned long long numeric;

            assert(field->type == MYSQL_TYPE_BIT);
            /* terminating with NULL */
            values[counter][*stmt->result_bind[counter].length]= '\0';
            numeric= strtoull(values[counter], NULL, 10);

            *stmt->result_bind[counter].length= (field->length+7)/8;
            numeric2binary(values[counter], numeric,
                          *stmt->result_bind[counter].length);

          }

          iprec= desc_get_rec(stmt->ipd, i, FALSE);
          aprec= desc_get_rec(stmt->apd, i, FALSE);
          assert(iprec && aprec);

          if (iprec->parameter_type == SQL_PARAM_INPUT_OUTPUT
           || iprec->parameter_type == SQL_PARAM_OUTPUT
  #ifndef USE_IODBC
           || iprec->parameter_type == SQL_PARAM_INPUT_OUTPUT_STREAM
           || iprec->parameter_type == SQL_PARAM_OUTPUT_STREAM
  #endif
          )
          {
            if (aprec->data_ptr)
            {
              unsigned long length= *stmt->result_bind[counter].length;
              char *target= NULL;
              SQLLEN *octet_length_ptr= NULL;
              SQLLEN *indicator_ptr= NULL;
              SQLINTEGER default_size;

              if (aprec->octet_length_ptr)
              {
                octet_length_ptr= (SQLLEN*)ptr_offset_adjust(aprec->octet_length_ptr,
                                              stmt->apd->bind_offset_ptr,
                                              stmt->apd->bind_type,
                                              sizeof(SQLLEN), 0);
              }

              indicator_ptr= (SQLLEN*)ptr_offset_adjust(aprec->indicator_ptr,
                                           stmt->apd->bind_offset_ptr,
                                           stmt->apd->bind_type,
                                           sizeof(SQLLEN), 0);

              default_size = bind_length(aprec->concise_type,
                                        (ulong)aprec->octet_length);
              target= (char*)ptr_offset_adjust(aprec->data_ptr, stmt->apd->bind_offset_ptr,
                                    stmt->apd->bind_type, default_size, 0);

              stmt->reset_getdata_position();

              if (iprec->parameter_type == SQL_PARAM_INPUT_OUTPUT
               || iprec->parameter_type == SQL_PARAM_OUTPUT)
              {
                sql_get_data(stmt, aprec->concise_type, counter,
                             target, aprec->octet_length, indicator_ptr,
                             values[counter], length, aprec);

                /* TODO: solve that globally */
                if (octet_length_ptr != NULL && indicator_ptr != NULL
                  && octet_length_ptr != indicator_ptr
                  && *indicator_ptr != SQL_NULL_DATA)
                {
                  *octet_length_ptr= *indicator_ptr;
                }
              }
              else if (octet_length_ptr != NULL)
              {
                /* Putting full number of bytes in the stream. A bit dirtyhackish.
                   Only good since only binary type is supported... */
                *octet_length_ptr= *stmt->result_bind[counter].length;
              }
            }

            ++counter;
          }
        }
      }
    }
    else /*values != NULL */
    {
      /* Something went wrong */
      stmt->out_params_state= OPS_UNKNOWN;
    }

    if (stmt->out_params_state != OPS_STREAMS_PENDING)
    {
      /* This MAGICAL fetch is required. If there are streams - it has to be after
         streams are all done, perhaps when stmt->out_params_state is changed from
         OPS_STREAMS_PENDING */
      mysql_stmt_fetch(stmt->ssps);
    }

    return TRUE;
  }
  return FALSE;
}