Esempio n. 1
0
static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_keys, int as_array) {
  VALUE row;
  /* Storing Values */
  unsigned int i;
  /* Wrapper And Local Vars */
  GET_RESULT_WRAPPER(self);
  /* Create Empty Row */
  row = as_array ? rb_ary_new2(rwrap->number_of_fields) : rb_hash_new();
  for (i = 0; i < rwrap->number_of_fields; i++) {
    VALUE val = Qnil;
    int col = i+1;
    int coltype = dbcoltype(rwrap->client, col);
    BYTE *data = dbdata(rwrap->client, col);
    DBINT data_len = dbdatlen(rwrap->client, col);
    int null_val = ((data == NULL) && (data_len == 0));
    if (!null_val) {
      switch(coltype) {
        case SYBINT1:
          val = INT2FIX(*(DBTINYINT *)data);
          break;
        case SYBINT2:
          val = INT2FIX(*(DBSMALLINT *)data);
          break;
        case SYBINT4:
          val = INT2NUM(*(DBINT *)data);
          break;
        case SYBINT8:
          val = LL2NUM(*(DBBIGINT *)data);
          break;
        case SYBBIT:
          val = *(int *)data ? Qtrue : Qfalse;
          break;
        case SYBNUMERIC:
        case SYBDECIMAL: {
          DBTYPEINFO *data_info = dbcoltypeinfo(rwrap->client, col);
          int data_slength = (int)data_info->precision + (int)data_info->scale + 1;
          char converted_decimal[data_slength];
          dbconvert(rwrap->client, coltype, data, data_len, SYBVARCHAR, (BYTE *)converted_decimal, -1);
          val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new2((char *)converted_decimal));
          break;
        }
        case SYBFLT8: {
          double col_to_double = *(double *)data;
          val = (col_to_double == 0.000000) ? opt_float_zero : rb_float_new(col_to_double);
          break;
        }
        case SYBREAL: {
          float col_to_float = *(float *)data;
          val = (col_to_float == 0.0) ? opt_float_zero : rb_float_new(col_to_float);
          break;
        }
        case SYBMONEY: {
          DBMONEY *money = (DBMONEY *)data;
          char converted_money[25];
          long long money_value = ((long long)money->mnyhigh << 32) | money->mnylow;
          sprintf(converted_money, "%" LONG_LONG_FORMAT, money_value);
          val = rb_funcall(cBigDecimal, intern_new, 2, rb_str_new2(converted_money), opt_four);
          val = rb_funcall(val, intern_divide, 1, opt_tenk);
          break;
        }
        case SYBMONEY4: {
          DBMONEY4 *money = (DBMONEY4 *)data;
          char converted_money[20];
          sprintf(converted_money, "%f", money->mny4 / 10000.0);
          val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new2(converted_money));
          break;
        }
        case SYBBINARY:
        case SYBIMAGE:
          val = rb_str_new((char *)data, (long)data_len);
          #ifdef HAVE_RUBY_ENCODING_H
            rb_enc_associate(val, binaryEncoding);
          #endif
          break;
        case 36: { // SYBUNIQUE
          char converted_unique[37];
          dbconvert(rwrap->client, coltype, data, 37, SYBVARCHAR, (BYTE *)converted_unique, -1);
          val = ENCODED_STR_NEW2(converted_unique);
          break;
        }
        case SYBDATETIME4: {
          DBDATETIME new_data;
          dbconvert(rwrap->client, coltype, data, data_len, SYBDATETIME, (BYTE *)&new_data, sizeof(new_data));
          data = (BYTE *)&new_data;
          data_len = sizeof(new_data);
        }
        case SYBDATETIME: {
          DBDATEREC dr;
          dbdatecrack(rwrap->client, &dr, (DBDATETIME *)data);
          if (dr.year + dr.month + dr.day + dr.hour + dr.minute + dr.second + dr.millisecond != 0) {
            val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr.year), INT2NUM(dr.month), INT2NUM(dr.day), INT2NUM(dr.hour), INT2NUM(dr.minute), INT2NUM(dr.second), INT2NUM(dr.millisecond*1000));
          }
          break;
        }
        case 40:   // SYBMSDATE
        case 41:   // SYBMSTIME
        case 42:   // SYBMSDATETIME2
        case 43: { // SYBMSDATETIMEOFFSET
          #ifdef DBVERSION_73
            if (dbtds(rwrap->client) >= DBTDS_7_3) {
              DBDATEREC2 dr2;
              dbanydatecrack(rwrap->client, &dr2, coltype, data);
              switch(coltype) {
                case 40: { // SYBMSDATE
                  val = rb_funcall(cDate, intern_new, 3, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day));
                  break;
                }
                case 41: { // SYBMSTIME
                  VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
                  val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(1900), INT2NUM(1), INT2NUM(1), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
                  break;
                }
                case 42: { // SYBMSDATETIME2
                  VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
                  val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
                  break;
                }
                case 43: { // SYBMSDATETIMEOFFSET
                  long long numerator = ((long)dr2.second * (long long)1000000000) + (long long)dr2.nanosecond;
                  VALUE rational_sec = rb_Rational(LL2NUM(numerator), opt_onebil);
                  val = rb_funcall(rb_cTime, intern_new, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), rational_sec, INT2NUM(dr2.tzone*60));
                  break;
                }
              }
            } else {
              val = ENCODED_STR_NEW(data, data_len);
            }
          #else
            val = ENCODED_STR_NEW(data, data_len);
          #endif
          break;
        }
        case SYBCHAR:
        case SYBTEXT:
          val = ENCODED_STR_NEW(data, data_len);
          break;
        default:
          val = ENCODED_STR_NEW(data, data_len);
          break;
      }
    }
    if (as_array) {
      rb_ary_store(row, i, val);
    } else {
      VALUE key;
      if (rwrap->number_of_results == 0) {
        key = rb_ary_entry(rwrap->fields, i);
      } else {
        key = rb_ary_entry(rb_ary_entry(rwrap->fields, rwrap->number_of_results), i);
      }
      rb_hash_aset(row, key, val);
    }
  }
  return row;
}
Esempio n. 2
0
File: rcsv.c Progetto: fiksu/rcsv
/* This procedure is called for every parsed field */
void end_of_field_callback(void * field, size_t field_size, void * data) {
  const char * field_str = (char *)field;
  struct rcsv_metadata * meta = (struct rcsv_metadata *) data;
  char row_conversion = 0;
  VALUE parsed_field;

  /* No need to parse anything until the end of the line if skip_current_row is set */
  if (meta->skip_current_row) {
    return;
  }

  /* Skip the row if its position is less than specifed offset */
  if (meta->current_row < meta->offset_rows) {
    meta->skip_current_row = true;
    return;
  }

  /* Get row conversion char specifier */
  if (meta->current_col < meta->num_row_conversions) {
    row_conversion = (char)meta->row_conversions[meta->current_col];
  }

  /* Convert the field from string into Ruby type specified by row_conversion */
  if (row_conversion != ' ') { /* spacebar skips the column */
    if (field_size == 0) {
      /* Assigning appropriate default value if applicable. */
      if (meta->current_col < meta->num_row_defaults) {
        parsed_field = meta->row_defaults[meta->current_col];
      } else { /* It depends on empty_field_is_nil if we convert empty strings to nils */
        if (meta->empty_field_is_nil || field_str == NULL) {
          parsed_field = Qnil;
        } else {
          parsed_field = ENCODED_STR_NEW("", 0, meta->encoding_index);
        }
      }
    } else {
      if (meta->current_col < meta->num_row_conversions) {
        switch (row_conversion){
          case 's': /* String */
            parsed_field = ENCODED_STR_NEW(field_str, field_size, meta->encoding_index);
            break;
          case 'i': /* Integer */
            parsed_field = LL2NUM(atoll(field_str));
            break;
          case 'f': /* Float */
            parsed_field = rb_float_new(atof(field_str));
            break;
          case 'b': /* TrueClass/FalseClass */
            switch (field_str[0]) {
              case 't':
              case 'T':
              case '1':
                parsed_field = Qtrue;
                break;
              case 'f':
              case 'F':
              case '0':
                parsed_field = Qfalse;
                break;
              default:
                RAISE_WITH_LOCATION(
                  meta->current_row,
                  meta->current_col,
                  field_str,
                  "Bad Boolean value. Valid values are strings where the first character is T/t/1 for true or F/f/0 for false."
                );
            }
            break;
          default:
            RAISE_WITH_LOCATION(
              meta->current_row,
              meta->current_col,
              field_str,
              "Unknown deserializer '%c'.",
              row_conversion
            );
        }
      } else { /* No conversion happens */
        parsed_field = ENCODED_STR_NEW(field_str, field_size, meta->encoding_index); /* field */
      }
    }

    /* Filter by row values listed in meta->only_rows */
    if ((meta->only_rows != NULL) &&
        (meta->current_col < meta->num_only_rows) &&
        (meta->only_rows[meta->current_col] != Qnil) &&
        (!rb_ary_includes(meta->only_rows[meta->current_col], parsed_field))) {
      meta->skip_current_row = true;
      return;
    }

    /* Filter out by row values listed in meta->except_rows */
    if ((meta->except_rows != NULL) &&
        (meta->current_col < meta->num_except_rows) &&
        (meta->except_rows[meta->current_col] != Qnil) &&
        (rb_ary_includes(meta->except_rows[meta->current_col], parsed_field))) {
      meta->skip_current_row = true;
      return;
    }

    /* Assign the value to appropriate hash key if parsing into Hash */
    if (meta->row_as_hash) {
      if (meta->current_col >= meta->num_columns) {
        RAISE_WITH_LOCATION(
          meta->current_row,
          meta->current_col,
          field_str,
          "There are at least %d columns in a row, which is beyond the number of provided column names (%d).",
          (int)meta->current_col + 1,
          (int)meta->num_columns
        );
      } else {
        rb_hash_aset(meta->last_entry, meta->column_names[meta->current_col], parsed_field); /* last_entry[column_names[current_col]] = field */
      }
    } else { /* Parse into Array */
      rb_ary_push(meta->last_entry, parsed_field); /* last_entry << field */
    }
  }

  /* Increment column counter */
  meta->current_col++;
  return;
}