Example #1
0
// NEEDS TO BE FINISHED WHEN PRIMITIVES ARE REDONE
static QualifiedType
returnInfoNumericUp(CallExpr* call) {
  Type* t1 = call->get(1)->typeInfo();
  Type* t2 = call->get(2)->typeInfo();
  if (is_int_type(t1) && is_real_type(t2))
    return QualifiedType(t2, QUAL_VAL);
  if (is_real_type(t1) && is_int_type(t2))
    return QualifiedType(t1, QUAL_VAL);
  if (is_int_type(t1) && is_bool_type(t2))
    return QualifiedType(t1, QUAL_VAL);
  if (is_bool_type(t1) && is_int_type(t2))
    return QualifiedType(t2, QUAL_VAL);
  return QualifiedType(t1, QUAL_VAL);
}
Example #2
0
// NEEDS TO BE FINISHED WHEN PRIMITIVES ARE REDONE
static Type*
returnInfoNumericUp(CallExpr* call) {
  Type* t1 = call->get(1)->typeInfo();
  Type* t2 = call->get(2)->typeInfo();
  if (is_int_type(t1) && is_real_type(t2))
    return t2;
  if (is_real_type(t1) && is_int_type(t2))
    return t1;
  if (is_int_type(t1) && is_bool_type(t2))
    return t1;
  if (is_bool_type(t1) && is_int_type(t2))
    return t2;
  return t1;
}
Example #3
0
IntentTag blankIntentForType(Type* t) {
  if (isSyncType(t) ||
      isAtomicType(t) ||
      t->symbol->hasFlag(FLAG_ARRAY)) {
    return INTENT_REF;
  } else if (is_bool_type(t) ||
             is_int_type(t) ||
             is_uint_type(t) ||
             is_real_type(t) ||
             is_imag_type(t) ||
             is_complex_type(t) ||
             is_enum_type(t) ||
             is_string_type(t) ||
             t == dtStringC ||
             t == dtStringCopy ||
             isClass(t) ||
             isRecord(t) ||
             isUnion(t) ||
             t == dtTaskID ||
             t == dtFile ||
             t == dtTaskList ||
             t == dtNil ||
             t == dtOpaque ||
             t->symbol->hasFlag(FLAG_DOMAIN) ||
             t->symbol->hasFlag(FLAG_DISTRIBUTION) ||
             t->symbol->hasFlag(FLAG_EXTERN)) {
    return constIntentForType(t);
  }
  INT_FATAL(t, "Unhandled type in blankIntentForType()");
  return INTENT_BLANK;
}
Example #4
0
static IntentTag constIntentForType(Type* t) {
  if (isSyncType(t) ||
      isRecordWrappedType(t) ||  // domain, array, or distribution
      isRecord(t) ||  // may eventually want to decide based on size
      is_string_type(t)) {  
    return INTENT_CONST_REF;
  } else if (is_bool_type(t) ||
             is_int_type(t) ||
             is_uint_type(t) ||
             is_real_type(t) ||
             is_imag_type(t) ||
             is_complex_type(t) ||
             is_enum_type(t) ||
             isClass(t) ||
             isUnion(t) ||
             isAtomicType(t) ||
             t == dtOpaque ||
             t == dtTaskID ||
             t == dtFile ||
             t == dtTaskList ||
             t == dtNil ||
             t == dtStringC ||
             t == dtStringCopy ||
             t->symbol->hasFlag(FLAG_EXTERN)) {
    return INTENT_CONST_IN;
  }
  INT_FATAL(t, "Unhandled type in constIntentForType()");
  return INTENT_CONST;
}
Example #5
0
static gboolean
iter_func (EggFmtIter *iter,
           gpointer    user_data)
{
	GIOChannel  *channel = user_data;
	gchar       *line    = NULL;
	gchar      **parts;
	gboolean     result  = FALSE;
	gint         i, v_int = 0;
	GType        vtype;

	if (G_IO_STATUS_NORMAL != g_io_channel_read_line (channel, &line, NULL, NULL, NULL))
		return FALSE;

	g_strstrip (line);
	parts = g_strsplit (line, "|", iter->n_columns);

	if (g_strv_length (parts) != iter->n_columns) {
		result = FALSE;
		goto cleanup;
	}

	for (i = 0; i < iter->n_columns; i++) {
		vtype = G_VALUE_TYPE (&iter->column_values [i]);

		if (is_int_type (vtype)) {
			parse_int (parts [i], &v_int);
			g_value_set_int (&iter->column_values [i], v_int);
		}
		else {
			g_value_set_string (&iter->column_values [i], parts [i]);
		}
	}

	result = TRUE;

cleanup:
	g_strfreev (parts);
	g_free (line);

	return result;
}
// Is this type OK to pass by value (e.g. it's reasonably-sized)?
static bool
passableByVal(Type* type) {
  if (is_bool_type(type)    ||
      is_int_type(type)     ||
      is_uint_type(type)    ||
      is_real_type(type)    ||
      is_imag_type(type)    ||
      is_complex_type(type) ||
      is_enum_type(type)    ||
      isClass(type)         ||
      type == dtTaskID      ||
      // For now, allow ranges as a special case, not records in general.
      type->symbol->hasFlag(FLAG_RANGE) ||
      0)
    return true;

  // TODO: allow reasonably-sized records. NB this-in-taskfns-in-ctors.chpl
  // TODO: allow reasonably-sized tuples - heterogeneous and homogeneous.

  return false;
}
Example #7
0
IntentTag blankIntentForType(Type* t) {
  IntentTag retval = INTENT_BLANK;

  if (isSyncType(t)                                  ||
      isAtomicType(t)                                ||
      t->symbol->hasFlag(FLAG_DEFAULT_INTENT_IS_REF) ||
      t->symbol->hasFlag(FLAG_ARRAY)) {
    retval = INTENT_REF;

  } else if (is_bool_type(t)                         ||
             is_int_type(t)                          ||
             is_uint_type(t)                         ||
             is_real_type(t)                         ||
             is_imag_type(t)                         ||
             is_complex_type(t)                      ||
             is_enum_type(t)                         ||
             t == dtStringC                          ||
             t == dtStringCopy                       ||
             t == dtCVoidPtr                         ||
             t == dtCFnPtr                           ||
             isClass(t)                              ||
             isRecord(t)                             ||
             isUnion(t)                              ||
             t == dtTaskID                           ||
             t == dtFile                             ||
             t == dtNil                              ||
             t == dtOpaque                           ||
             t->symbol->hasFlag(FLAG_DOMAIN)         ||
             t->symbol->hasFlag(FLAG_DISTRIBUTION)   ||
             t->symbol->hasFlag(FLAG_EXTERN)) {
    retval = constIntentForType(t);

  } else {
    INT_FATAL(t, "Unhandled type in blankIntentForType()");
  }

  return retval;
}
Example #8
0
static MonoInst*
emit_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args, const MagicTypeInfo *info)
{
	int i = 0;
	const char *name = cmethod->name;
	MonoInst *ins;
	int type_index, stack_type;

	if (info->op_index == 2 && cfg->r4fp && SIZEOF_VOID_P == 4) {
		type_index = 3;
		stack_type = STACK_R4;
	} else {
		type_index = info->op_index;
		stack_type = info->stack_type;
	}

	if (!strcmp ("op_Implicit", name) || !strcmp ("op_Explicit", name)) {
		int source_size = type_size (cfg, fsig->params [0]);
		int dest_size = type_size (cfg, fsig->ret);

		switch (info->big_stack_type) {
		case STACK_I8:
			if (!is_int_type (fsig->params [0]) || !is_int_type (fsig->ret))
				return NULL;
			break;
		case STACK_R8:
			if (!is_float_type (fsig->params [0]) || !is_float_type (fsig->ret))
				return NULL;
			break;
		default:
			g_assert_not_reached ();
		}

		//4 -> 4 or 8 -> 8
		if (source_size == dest_size)
			return args [0];

		//4 -> 8
		if (source_size < dest_size)
			return emit_widen (cfg, info, args [0]->dreg);

		//8 -> 4
		return emit_narrow (cfg, info, args [0]->dreg);
	}

	if (!strcmp (".ctor", name)) {
		gboolean is_ldaddr = args [0]->opcode == OP_LDADDR;
		int arg0 = args [1]->dreg;
		int arg_size = type_size (cfg, fsig->params [0]);

		if (arg_size > SIZEOF_VOID_P) //8 -> 4
			arg0 = emit_narrow (cfg, info, arg0)->dreg;
		else if (arg_size < SIZEOF_VOID_P) //4 -> 8
			arg0 = emit_widen (cfg, info, arg0)->dreg;

		if (is_ldaddr) { /*Eliminate LDADDR if it's initing a local var*/
			int dreg = ((MonoInst*)args [0]->inst_p0)->dreg;
			NULLIFY_INS (args [0]);
			EMIT_NEW_UNALU (cfg, ins, info->move, dreg, arg0);
			cfg->has_indirection = TRUE;
		} else {
			EMIT_NEW_STORE_MEMBASE (cfg, ins, info->store_op, args [0]->dreg, 0, arg0);
		}
		return ins;
	}

	if (!strcmp ("op_Increment", name) || !strcmp ("op_Decrement", name)) {
		gboolean inc = !strcmp ("op_Increment", name);
		/* FIXME float inc is too complex to bother with*/
		//this is broken with ints too
		// if (!info->inc_op)
			return NULL;

		/* We have IR for inc/dec */
		MONO_INST_NEW (cfg, ins, inc ? info->inc_op : info->dec_op);
		ins->dreg = alloc_dreg (cfg, info->stack_type);
		ins->sreg1 = args [0]->dreg;
		ins->inst_imm = 1;
		ins->type = info->stack_type;
		MONO_ADD_INS (cfg->cbb, ins);
		return ins;
	}

	for (i = 0; i < sizeof (int_binop) / sizeof  (IntIntrisic); ++i) {
		if (!strcmp (int_binop [i].op_name, name)) {
			if (!int_binop [i].op_table [info->op_index])
				return NULL;
			g_assert (int_binop [i].op_table [type_index]);

			MONO_INST_NEW (cfg, ins, int_binop [i].op_table [type_index]);
			ins->dreg = alloc_dreg (cfg, stack_type);
			ins->sreg1 = args [0]->dreg;
	        ins->sreg2 = args [1]->dreg;
			ins->type = stack_type;
			MONO_ADD_INS (cfg->cbb, ins);
			return mono_decompose_opcode (cfg, ins);
		}
	}

	for (i = 0; i < sizeof (int_unnop) / sizeof  (IntIntrisic); ++i) {
		if (!strcmp (int_unnop [i].op_name, name)) {
			g_assert (int_unnop [i].op_table [type_index]);

			MONO_INST_NEW (cfg, ins, int_unnop [i].op_table [type_index]);
			ins->dreg = alloc_dreg (cfg, stack_type);
			ins->sreg1 = args [0]->dreg;
			ins->type = stack_type;
			MONO_ADD_INS (cfg->cbb, ins);
			return ins;
		}
	}

	for (i = 0; i < sizeof (int_cmpop) / sizeof  (IntIntrisic); ++i) {
		if (!strcmp (int_cmpop [i].op_name, name)) {
			short op_cmp = int_cmpop [i].op_table [type_index];

			g_assert (op_cmp);

			if (info->compare_op) {
				MONO_INST_NEW (cfg, ins, info->compare_op);
		        ins->dreg = -1;
				ins->sreg1 = args [0]->dreg;
		        ins->sreg2 = args [1]->dreg;
				MONO_ADD_INS (cfg->cbb, ins);

				MONO_INST_NEW (cfg, ins, op_cmp);
		        ins->dreg = alloc_preg (cfg);
				ins->type = STACK_I4;
				MONO_ADD_INS (cfg->cbb, ins);
			} else {
				MONO_INST_NEW (cfg, ins, op_cmp);
				guint32 fcmp_dreg = ins->dreg = alloc_ireg (cfg);
				ins->sreg1 = args [0]->dreg;
		        ins->sreg2 = args [1]->dreg;
				MONO_ADD_INS (cfg->cbb, ins);
				if (op_cmp == OP_FCLT_UN || op_cmp == OP_FCGT_UN || op_cmp == OP_RCLT_UN || op_cmp == OP_RCGT_UN) {
					/* we have to negate the result of this comparison:
					 *  - op_GreaterThanOrEqual maps to NOT x OP_FCLT_UN / OP_RCLT_UN
					 *  - op_LessThanOrEqual    maps to NOT x OP_FCGT_UN / OP_RCGT_UN
					 *
					 *  this matches generated bytecode by C# when doing the
					 *  same operations on float/double. the `_UN` suffix says
					 *  that if an operand is NaN, the result is true. If
					 *  OP_FCGE/OP_FCLE is used, it is mapped to instructions
					 *  on some architectures that don't detect NaN. For
					 *  example, on arm64 the condition `eq` doesn't respect
					 *  NaN results of a `fcmp` instruction.
					 */
					MONO_INST_NEW (cfg, ins, OP_ICOMPARE_IMM);
					ins->dreg = -1;
					ins->sreg1 = fcmp_dreg;
					ins->inst_imm = 0;
					MONO_ADD_INS (cfg->cbb, ins);

					MONO_INST_NEW (cfg, ins, OP_CEQ);
					ins->dreg = alloc_preg (cfg);
					ins->type = STACK_I4;
					MONO_ADD_INS (cfg->cbb, ins);
				}
			}

			return ins;
		}
	}

	return NULL;
}
Example #9
0
CallExpr* ParamForLoop::foldForResolve()
{
  SymExpr*   idxExpr   = indexExprGet();
  SymExpr*   lse       = lowExprGet();
  SymExpr*   hse       = highExprGet();
  SymExpr*   sse       = strideExprGet();

  if (!lse             || !hse             || !sse)
    USR_FATAL(this, "param for loop must be defined over a bounded param range");

  VarSymbol* lvar      = toVarSymbol(lse->var);
  VarSymbol* hvar      = toVarSymbol(hse->var);
  VarSymbol* svar      = toVarSymbol(sse->var);

  CallExpr*  noop      = new CallExpr(PRIM_NOOP);

  if (!lvar            || !hvar            || !svar)
    USR_FATAL(this, "param for loop must be defined over a bounded param range");

  if (!lvar->immediate || !hvar->immediate || !svar->immediate)
    USR_FATAL(this, "param for loop must be defined over a bounded param range");

  Symbol*      idxSym  = idxExpr->var;
  Symbol*      continueSym = continueLabelGet();
  Type*        idxType = indexType();
  IF1_int_type idxSize = (get_width(idxType) == 32) ? INT_SIZE_32 : INT_SIZE_64;

  // Insert an "insertion marker" for loop unrolling
  insertAfter(noop);

  if (is_int_type(idxType))
  {
    int64_t low    = lvar->immediate->to_int();
    int64_t high   = hvar->immediate->to_int();
    int64_t stride = svar->immediate->to_int();

    if (stride <= 0)
    {
      for (int64_t i = high; i >= low; i += stride)
      {
        SymbolMap map;

        map.put(idxSym, new_IntSymbol(i, idxSize));
        copyBodyHelper(noop, i, &map, this, continueSym);
      }
    }
    else
    {
      for (int64_t i = low; i <= high; i += stride)
      {
        SymbolMap map;

        map.put(idxSym, new_IntSymbol(i, idxSize));

        copyBodyHelper(noop, i, &map, this, continueSym);
      }
    }
  }
  else
  {
    INT_ASSERT(is_uint_type(idxType) || is_bool_type(idxType));

    uint64_t low    = lvar->immediate->to_uint();
    uint64_t high   = hvar->immediate->to_uint();
    int64_t  stride = svar->immediate->to_int();

    if (stride <= 0)
    {
      for (uint64_t i = high; i >= low; i += stride)
      {
        SymbolMap map;

        map.put(idxSym, new_UIntSymbol(i, idxSize));

        copyBodyHelper(noop, i, &map, this, continueSym);
      }
    }
    else
    {
      for (uint64_t i = low; i <= high; i += stride)
      {
        SymbolMap map;

        map.put(idxSym, new_UIntSymbol(i, idxSize));

        copyBodyHelper(noop, i, &map, this, continueSym);
      }
    }
  }

  // Remove the "insertion marker"
  noop->remove();

  // Replace the paramLoop with the NO-OP
  replace(noop);

  return noop;
}
Example #10
0
static MonoInst*
emit_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args, const MagicTypeInfo *info)
{
	int i = 0;
	const char *name = cmethod->name;
	MonoInst *ins;
	int type_index, stack_type;

	if (info->op_index == 2 && cfg->r4fp && SIZEOF_VOID_P == 4) {
		type_index = 3;
		stack_type = STACK_R4;
	} else {
		type_index = info->op_index;
		stack_type = info->stack_type;
	}

	if (!strcmp ("op_Implicit", name) || !strcmp ("op_Explicit", name)) {
		int source_size = type_size (cfg, fsig->params [0]);
		int dest_size = type_size (cfg, fsig->ret);

		switch (info->big_stack_type) {
		case STACK_I8:
			if (!is_int_type (fsig->params [0]) || !is_int_type (fsig->ret))
				return NULL;
			break;
		case STACK_R8:
			if (!is_float_type (fsig->params [0]) || !is_float_type (fsig->ret))
				return NULL;
			break;
		default:
			g_assert_not_reached ();
		}

		//4 -> 4 or 8 -> 8
		if (source_size == dest_size)
			return args [0];

		//4 -> 8
		if (source_size < dest_size)
			return emit_widen (cfg, info, args [0]->dreg);

		//8 -> 4
		return emit_narrow (cfg, info, args [0]->dreg);
	}

	if (!strcmp (".ctor", name)) {
		gboolean is_ldaddr = args [0]->opcode == OP_LDADDR;
		int arg0 = args [1]->dreg;
		int arg_size = type_size (cfg, fsig->params [0]);

		if (arg_size > SIZEOF_VOID_P) //8 -> 4
			arg0 = emit_narrow (cfg, info, arg0)->dreg;
		else if (arg_size < SIZEOF_VOID_P) //4 -> 8
			arg0 = emit_widen (cfg, info, arg0)->dreg;

		if (is_ldaddr) { /*Eliminate LDADDR if it's initing a local var*/
			int dreg = ((MonoInst*)args [0]->inst_p0)->dreg;
			NULLIFY_INS (args [0]);
			EMIT_NEW_UNALU (cfg, ins, info->move, dreg, arg0);
			cfg->has_indirection = TRUE;
		} else {
			EMIT_NEW_STORE_MEMBASE (cfg, ins, info->store_op, args [0]->dreg, 0, arg0);
		}
		return ins;
	}

	if (!strcmp ("op_Increment", name) || !strcmp ("op_Decrement", name)) {
		gboolean inc = !strcmp ("op_Increment", name);
		/* FIXME float inc is too complex to bother with*/
		//this is broken with ints too
		// if (!info->inc_op)
			return NULL;

		/* We have IR for inc/dec */
		MONO_INST_NEW (cfg, ins, inc ? info->inc_op : info->dec_op);
		ins->dreg = alloc_dreg (cfg, info->stack_type);
		ins->sreg1 = args [0]->dreg;
		ins->inst_imm = 1;
		ins->type = info->stack_type;
		MONO_ADD_INS (cfg->cbb, ins);
		return ins;
	}

	for (i = 0; i < sizeof (int_binop) / sizeof  (IntIntrisic); ++i) {
		if (!strcmp (int_binop [i].op_name, name)) {
			if (!int_binop [i].op_table [info->op_index])
				return NULL;
			g_assert (int_binop [i].op_table [type_index]);

			MONO_INST_NEW (cfg, ins, int_binop [i].op_table [type_index]);
			ins->dreg = alloc_dreg (cfg, stack_type);
			ins->sreg1 = args [0]->dreg;
	        ins->sreg2 = args [1]->dreg;
			ins->type = stack_type;
			MONO_ADD_INS (cfg->cbb, ins);
			return mono_decompose_opcode (cfg, ins);
		}
	}

	for (i = 0; i < sizeof (int_unnop) / sizeof  (IntIntrisic); ++i) {
		if (!strcmp (int_unnop [i].op_name, name)) {
			g_assert (int_unnop [i].op_table [type_index]);

			MONO_INST_NEW (cfg, ins, int_unnop [i].op_table [type_index]);
			ins->dreg = alloc_dreg (cfg, stack_type);
			ins->sreg1 = args [0]->dreg;
			ins->type = stack_type;
			MONO_ADD_INS (cfg->cbb, ins);
			return ins;
		}
	}

	for (i = 0; i < sizeof (int_cmpop) / sizeof  (IntIntrisic); ++i) {
		if (!strcmp (int_cmpop [i].op_name, name)) {
			g_assert (int_cmpop [i].op_table [type_index]);

			if (info->compare_op) {
				MONO_INST_NEW (cfg, ins, info->compare_op);
		        ins->dreg = -1;
				ins->sreg1 = args [0]->dreg;
		        ins->sreg2 = args [1]->dreg;
				MONO_ADD_INS (cfg->cbb, ins);

				MONO_INST_NEW (cfg, ins, int_cmpop [i].op_table [type_index]);
		        ins->dreg = alloc_preg (cfg);
				ins->type = STACK_I4;
				MONO_ADD_INS (cfg->cbb, ins);
			} else {
				MONO_INST_NEW (cfg, ins, int_cmpop [i].op_table [type_index]);
				ins->dreg = alloc_ireg (cfg);
				ins->sreg1 = args [0]->dreg;
		        ins->sreg2 = args [1]->dreg;
				MONO_ADD_INS (cfg->cbb, ins);
			}

			return ins;
		}
	}

	return NULL;
}
Example #11
0
bool
DbUtil::runQuery(const char* sql,
                    const Properties& args,
                    SqlResultSet& rows){

  rows.clear();
  if (!isConnected())
    return false;

  g_debug << "runQuery: " << endl
          << " sql: '" << sql << "'" << endl;


  MYSQL_STMT *stmt= mysql_stmt_init(m_mysql);
  if (mysql_stmt_prepare(stmt, sql, strlen(sql)))
  {
    g_err << "Failed to prepare: " << mysql_error(m_mysql) << endl;
    return false;
  }

  uint params= mysql_stmt_param_count(stmt);
  MYSQL_BIND bind_param[params];
  bzero(bind_param, sizeof(bind_param));

  for(uint i= 0; i < mysql_stmt_param_count(stmt); i++)
  {
    BaseString name;
    name.assfmt("%d", i);
    // Parameters are named 0, 1, 2...
    if (!args.contains(name.c_str()))
    {
      g_err << "param " << i << " missing" << endl;
      assert(false);
    }
    PropertiesType t;
    Uint32 val_i;
    const char* val_s;
    args.getTypeOf(name.c_str(), &t);
    switch(t) {
    case PropertiesType_Uint32:
      args.get(name.c_str(), &val_i);
      bind_param[i].buffer_type= MYSQL_TYPE_LONG;
      bind_param[i].buffer= (char*)&val_i;
      g_debug << " param" << name.c_str() << ": " << val_i << endl;
      break;
    case PropertiesType_char:
      args.get(name.c_str(), &val_s);
      bind_param[i].buffer_type= MYSQL_TYPE_STRING;
      bind_param[i].buffer= (char*)val_s;
      bind_param[i].buffer_length= strlen(val_s);
      g_debug << " param" << name.c_str() << ": " << val_s << endl;
      break;
    default:
      assert(false);
      break;
    }
  }
  if (mysql_stmt_bind_param(stmt, bind_param))
  {
    g_err << "Failed to bind param: " << mysql_error(m_mysql) << endl;
    mysql_stmt_close(stmt);
    return false;
  }

  if (mysql_stmt_execute(stmt))
  {
    g_err << "Failed to execute: " << mysql_error(m_mysql) << endl;
    mysql_stmt_close(stmt);
    return false;
  }

  /*
    Update max_length, making it possible to know how big
    buffers to allocate
  */
  my_bool one= 1;
  mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one);

  if (mysql_stmt_store_result(stmt))
  {
    g_err << "Failed to store result: " << mysql_error(m_mysql) << endl;
    mysql_stmt_close(stmt);
    return false;
  }

  uint row= 0;
  MYSQL_RES* res= mysql_stmt_result_metadata(stmt);
  if (res != NULL)
  {
    MYSQL_FIELD *fields= mysql_fetch_fields(res);
    uint num_fields= mysql_num_fields(res);
    MYSQL_BIND bind_result[num_fields];
    bzero(bind_result, sizeof(bind_result));

    for (uint i= 0; i < num_fields; i++)
    {
      if (is_int_type(fields[i].type)){
        bind_result[i].buffer_type= MYSQL_TYPE_LONG;
        bind_result[i].buffer= malloc(sizeof(int));
      }
      else
      {
        uint max_length= fields[i].max_length + 1;
        bind_result[i].buffer_type= MYSQL_TYPE_STRING;
        bind_result[i].buffer= malloc(max_length);
        bind_result[i].buffer_length= max_length;
      }
    }

    if (mysql_stmt_bind_result(stmt, bind_result)){
      g_err << "Failed to bind result: " << mysql_error(m_mysql) << endl;
      mysql_stmt_close(stmt);
      return false;
    }

    while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
    {
      Properties curr(true);
      for (uint i= 0; i < num_fields; i++){
        if (is_int_type(fields[i].type))
          curr.put(fields[i].name, *(int*)bind_result[i].buffer);
        else
          curr.put(fields[i].name, (char*)bind_result[i].buffer);
      }
      rows.put("row", row++, &curr);
    }

    mysql_free_result(res);

    for (uint i= 0; i < num_fields; i++)
      free(bind_result[i].buffer);

  }

  // Save stats in result set
  rows.put("rows", row);
  rows.put("affected_rows", mysql_affected_rows(m_mysql));
  rows.put("mysql_errno", mysql_errno(m_mysql));
  rows.put("mysql_error", mysql_error(m_mysql));
  rows.put("mysql_sqlstate", mysql_sqlstate(m_mysql));
  rows.put("insert_id", mysql_insert_id(m_mysql));

  mysql_stmt_close(stmt);
  return true;
}