MySQLStmtVariables::MySQLStmtVariables(const Array& arr): m_arr(arr) { int count = m_arr.size(); m_vars = (MYSQL_BIND*)smart_calloc(count, sizeof(MYSQL_BIND)); m_null = (my_bool*)smart_calloc(count, sizeof(my_bool)); m_length = (unsigned long*)smart_calloc(count, sizeof(unsigned long)); for (int i = 0; i < count; i++) { m_null[i] = false; m_length[i] = 0; MYSQL_BIND *b = &m_vars[i]; b->is_null = &m_null[i]; b->length = &m_length[i]; b->buffer = nullptr; b->buffer_length = 0; b->buffer_type = MYSQL_TYPE_STRING; } }
HOT_FUNC CVarRef SharedMap::getValueRef(ssize_t pos) const { SharedVariant *sv = getValueImpl(pos); DataType t = sv->getType(); if (!IS_REFCOUNTED_TYPE(t)) return sv->asCVarRef(); if (LIKELY(m_localCache != nullptr)) { assert(unsigned(pos) < size()); TypedValue* tv = &m_localCache[pos]; if (tv->m_type != KindOfUninit) return tvAsCVarRef(tv); } else { static_assert(KindOfUninit == 0, "must be 0 since we use smart_calloc"); m_localCache = (TypedValue*) smart_calloc(size(), sizeof(TypedValue)); } TypedValue* tv = &m_localCache[pos]; tvAsVariant(tv) = sv->toLocal(); assert(tv->m_type != KindOfUninit); return tvAsCVarRef(tv); }
const Variant& APCLocalArray::GetValueRef(const ArrayData* adIn, ssize_t pos) { auto const ad = asApcArray(adIn); auto const sv = ad->m_arr->getValue(pos); if (LIKELY(ad->m_localCache != nullptr)) { assert(unsigned(pos) < ad->m_arr->capacity()); TypedValue* tv = &ad->m_localCache[pos]; if (tv->m_type != KindOfUninit) { return tvAsCVarRef(tv); } } else { static_assert(KindOfUninit == 0, "must be 0 since we use smart_calloc"); unsigned cap = ad->m_arr->capacity(); ad->m_localCache = static_cast<TypedValue*>( smart_calloc(cap, sizeof(TypedValue)) ); } auto const tv = &ad->m_localCache[pos]; tvAsVariant(tv) = sv->toLocal(); assert(tv->m_type != KindOfUninit); return tvAsCVarRef(tv); }
CVarRef APCLocalArray::getValueRef(ssize_t pos) const { APCHandle *sv = m_arr->getValue(pos); DataType t = sv->getType(); if (!IS_REFCOUNTED_TYPE(t)) { return APCTypedValue::fromHandle(sv)->asCVarRef(); } if (LIKELY(m_localCache != nullptr)) { assert(unsigned(pos) < m_arr->capacity()); TypedValue* tv = &m_localCache[pos]; if (tv->m_type != KindOfUninit) { return tvAsCVarRef(tv); } } else { static_assert(KindOfUninit == 0, "must be 0 since we use smart_calloc"); unsigned cap = m_arr->capacity(); m_localCache = (TypedValue*) smart_calloc(cap, sizeof(TypedValue)); } TypedValue* tv = &m_localCache[pos]; tvAsVariant(tv) = sv->toLocal(); assert(tv->m_type != KindOfUninit); return tvAsCVarRef(tv); }
bool MySQLStmtVariables::bind_result(MYSQL_STMT *stmt) { assert(m_arr.size() == mysql_stmt_field_count(stmt)); MYSQL_RES *res = mysql_stmt_result_metadata(stmt); MYSQL_FIELD *fields = mysql_fetch_fields(res); for(int i = 0; i < m_arr.size(); i++) { MYSQL_BIND *b = &m_vars[i]; b->is_unsigned = (fields[i].flags & UNSIGNED_FLAG) ? 1 : 0; switch (fields[i].type) { case MYSQL_TYPE_NULL: b->buffer_type = MYSQL_TYPE_NULL; case MYSQL_TYPE_DOUBLE: case MYSQL_TYPE_FLOAT: b->buffer_type = MYSQL_TYPE_DOUBLE; b->buffer_length = sizeof(double); break; case MYSQL_TYPE_LONGLONG: #if MYSQL_VERSION_ID > 50002 case MYSQL_TYPE_BIT: #endif case MYSQL_TYPE_LONG: case MYSQL_TYPE_INT24: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_YEAR: case MYSQL_TYPE_TINY: b->buffer_type = MYSQL_TYPE_LONGLONG; b->buffer_length = sizeof(int64_t); break; case MYSQL_TYPE_DATE: case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_TIME: case MYSQL_TYPE_STRING: case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: b->buffer_type = MYSQL_TYPE_STRING; b->buffer_length = fields[i].max_length ? fields[i].max_length : fields[i].length; break; default: // There exists some more types in this enum like MYSQL_TYPE_TIMESTAMP2, // MYSQL_TYPE_DATETIME2, MYSQL_TYPE_TIME2 but they are just used on the // server assert(false); } if (b->buffer_length > 0) { b->buffer = smart_calloc(1, b->buffer_length); } } mysql_free_result(res); return !mysql_stmt_bind_result(stmt, m_vars); }