static SQLRETURN batch_insert_std()

in driver/cursor.cc [1351:1565]


static SQLRETURN batch_insert_std( STMT *stmt, SQLULEN irow, std::string &query )
{
    MYSQL_RES    *result= stmt->result;     /* result set we are working with */
    SQLULEN      insert_count= 1;           /* num rows to insert - will be real value when row is 0 (all)  */
    SQLULEN      count= 0;                  /* current row */
    SQLLEN       length;
    SQLUSMALLINT ncol;
    long i;
    size_t       query_length= 0;           /* our original query len so we can reset pos if break_insert   */
    my_bool      break_insert= FALSE;       /* true if we are to exceed max data size for transmission
                                               but this seems to be misused */
    DESCREC aprec_(DESC_PARAM, DESC_APP),
            iprec_(DESC_PARAM, DESC_IMP);

    DESCREC *aprec= &aprec_, *iprec= &iprec_;
    SQLRETURN res;

    stmt->stmt_options.bookmark_insert= FALSE;

    /* determine the number of rows to insert when irow = 0 */
    if ( !irow && stmt->ard->array_size > 1 ) /* batch wise */
    {
        insert_count= stmt->ard->array_size;
        query_length= query.size();
    }

    do
    {
        /* Have we called exec_stmt_query() as a result of exceeding data size for transmission? If
           so then we need to reset the pos. and start building a new statement. */
        if ( break_insert )
        {
            query.erase(query_length);
        }

        /* For each row, build the value list from its columns */
        while (count < insert_count)
        {
            /* Append values for each column. */
            query.append("(");
            for ( ncol= 0; ncol < result->field_count; ++ncol )
            {
                MYSQL_FIELD *field= mysql_fetch_field_direct(result, ncol);
                DESCREC     *arrec;
                SQLLEN       ind_or_len= 0;

                arrec= desc_get_rec(stmt->ard, ncol, FALSE);
                /* if there's a separate APD for this (dae), use it */
                if (stmt->setpos_apd)
                  aprec= desc_get_rec(stmt->setpos_apd.get(), ncol, FALSE);
                else
                  aprec->reset_to_defaults();

                if (arrec)
                {
                  if (aprec->par.is_dae)
                    ind_or_len= aprec->par.val_length();
                  else if (arrec->octet_length_ptr)
                    ind_or_len= *(SQLLEN *)
                                ptr_offset_adjust(arrec->octet_length_ptr,
                                                  stmt->ard->bind_offset_ptr,
                                                  stmt->ard->bind_type,
                                                  sizeof(SQLLEN), count);
                  else
                    ind_or_len= arrec->octet_length;

                  iprec->concise_type= get_sql_data_type(stmt, field, NULL);
                  aprec->concise_type= arrec->concise_type;
                  aprec->type= get_type_from_concise_type(aprec->concise_type);

                  /* If column buffer type is interval - making sql type interval too. Making it for 2 supported interval types so far */
                  if (aprec->type == SQL_INTERVAL && (aprec->concise_type == SQL_C_INTERVAL_HOUR_TO_SECOND || aprec->concise_type == SQL_C_INTERVAL_HOUR_TO_MINUTE)
                    && (iprec->concise_type == SQL_TYPE_TIME || iprec->concise_type == SQL_TIME))
                  {
                    iprec->type= aprec->type;
                    iprec->concise_type= aprec->concise_type;
                  }

                  /* copy prec and scale - needed for SQL_NUMERIC values */
                  iprec->precision= arrec->precision;
                  iprec->scale= arrec->scale;

                  if (stmt->dae_type && aprec->par.is_dae)
                    /* arrays or offsets are not supported for data-at-exec */
                    aprec->data_ptr= aprec->par.val();
                  else
                    aprec->data_ptr= ptr_offset_adjust(arrec->data_ptr,
                                                       stmt->ard->bind_offset_ptr,
                                                       stmt->ard->bind_type,
                                                       bind_length(arrec->concise_type,
                                                                   (ulong)arrec->octet_length),
                                                       count);
                }

                switch (ind_or_len) {
                case SQL_NTS:
                  if (aprec->data_ptr)
                    length= strlen((const char*)aprec->data_ptr);
                  break;

                /*
                  We pass through SQL_COLUMN_IGNORE and SQL_NULL_DATA,
                  because the insert_data() that is eventually called knows
                  how to deal with them.
                */
                case SQL_COLUMN_IGNORE:
                case SQL_NULL_DATA:
                default:
                  length= ind_or_len;
                }

                aprec->octet_length_ptr= &length;
                aprec->indicator_ptr= &length;

                if (copy_rowdata(stmt, aprec, iprec) != SQL_SUCCESS)
                  return SQL_ERROR;

            } /* END OF for (ncol= 0; ncol < result->field_count; ++ncol) */

            length = stmt->buf_pos();
            query.append(stmt->buf(), length - 1);
            stmt->buf_set_pos(0); // Buffer is used, can be reset
            query.append("),");
            ++count;

            /*
              We have a limited capacity to shove data across the wire, but
              we handle this by sending in multiple calls to exec_stmt_query()
            */
            if (query.size() + length >= (SQLULEN) stmt->buf_len())
            {
                break_insert= TRUE;
                break;
            }

        }  /* END OF while(count < insert_count) */

        query.erase(query.size() - 1);
        if ( exec_stmt_query_std(stmt, query, false) !=
             SQL_SUCCESS )
            return(SQL_ERROR);

    } while ( break_insert && count < insert_count );


    if (stmt->stmt_options.bookmarks == SQL_UB_VARIABLE)
    {
      ulong copy_bytes= 0;
      DESCREC *arrec;
      long max_row;

      arrec= desc_get_rec(stmt->ard, -1, FALSE);
      max_row= (long) num_rows(stmt);

      if (ARD_IS_BOUND(arrec))
      {
        SQLLEN *pcbValue= NULL;
        SQLPOINTER TargetValuePtr= NULL;

        for (i= max_row; i < (SQLINTEGER)insert_count; ++i)
        {
          pcbValue= NULL;
          TargetValuePtr= NULL;

          stmt->reset_getdata_position();

          if (arrec->data_ptr)
          {
            TargetValuePtr= ptr_offset_adjust(arrec->data_ptr,
                                              stmt->ard->bind_offset_ptr,
                                              stmt->ard->bind_type,
                                              (SQLINTEGER)arrec->octet_length,
                                              i);
          }

          if (arrec->octet_length_ptr)
          {
            pcbValue= (SQLLEN*)ptr_offset_adjust(arrec->octet_length_ptr,
                                          (SQLULEN*)stmt->ard->bind_offset_ptr,
                                          stmt->ard->bind_type,
                                          sizeof(SQLLEN), i);
          }
          std::string sval = std::to_string(i + 1);
          res = sql_get_bookmark_data(stmt, arrec->concise_type, (uint)0,
                                TargetValuePtr, arrec->octet_length,
                                pcbValue, (char*)sval.data(),
                                (ulong)sval.length(), arrec);

          if (!SQL_SUCCEEDED(res))
          {
            return SQL_ERROR;
          }
        }

        stmt->ard->array_size= insert_count;
        stmt->stmt_options.bookmark_insert= TRUE;
      }
    }

    global_set_affected_rows(stmt, insert_count);

    /* update row status pointer(s) */
    if (stmt->ird->array_status_ptr)
    {
      for (count= insert_count; count--; )
        stmt->ird->array_status_ptr[count]= SQL_ROW_ADDED;
    }
    if (stmt->stmt_options.rowStatusPtr_ex)
    {
      for (count= insert_count; count--; )
        stmt->stmt_options.rowStatusPtr_ex[count]= SQL_ROW_ADDED;
    }

    return SQL_SUCCESS;
}