1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

mysql: allocate memory for each string and blob dynamically depending on its value length (#18214)

This commit is contained in:
Mark aka walkingdevel
2023-05-21 13:24:43 +00:00
committed by GitHub
parent f833188234
commit ce0591da8d
2 changed files with 45 additions and 26 deletions

View File

@ -3,10 +3,6 @@ module mysql
import orm
import time
type Prims = f32 | f64 | i16 | i64 | i8 | int | string | u16 | u32 | u64 | u8
// sql expr
// @select is used internally by V's ORM for processing `SELECT ` queries
pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive {
query := orm.orm_select_gen(config, '`', false, '?', 0, where)
@ -28,8 +24,8 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
mut dataptr := []&u8{}
for i in 0 .. num_fields {
f := unsafe { fields[i] }
match unsafe { FieldType(f.@type) } {
field := unsafe { fields[i] }
match unsafe { FieldType(field.@type) } {
.type_tiny {
dataptr << unsafe { malloc(1) }
}
@ -51,38 +47,40 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
.type_time, .type_date, .type_datetime, .type_time2, .type_datetime2 {
dataptr << unsafe { malloc(sizeof(C.MYSQL_TIME)) }
}
.type_string, .type_blob {
dataptr << unsafe { malloc(512) }
}
.type_var_string {
dataptr << unsafe { malloc(2) }
.type_string, .type_var_string, .type_blob, .type_tiny_blob, .type_medium_blob,
.type_long_blob {
// Memory will be allocated later dynamically depending on the length of the value.
dataptr << &u8(0)
}
else {
return error('\'${unsafe { FieldType(f.@type) }}\' is not yet implemented. Please create a new issue at https://github.com/vlang/v/issues/new')
return error('\'${unsafe { FieldType(field.@type) }}\' is not yet implemented. Please create a new issue at https://github.com/vlang/v/issues/new')
}
}
}
lens := []u32{len: int(num_fields), init: 0}
stmt.bind_res(fields, dataptr, lens, num_fields)
lengths := []u32{len: int(num_fields), init: 0}
stmt.bind_res(fields, dataptr, lengths, num_fields)
mut row := 0
mut types := config.types.clone()
mut field_types := []FieldType{}
if config.is_count {
types = [orm.type_idx['u64']]
}
// Map stores column indexes and their binds in order to extract values
// for these columns separately, with individual memory allocation for each value.
mut string_binds_map := map[int]C.MYSQL_BIND{}
for i, mut mysql_bind in stmt.res {
f := unsafe { fields[i] }
field_types << unsafe { FieldType(f.@type) }
field := unsafe { fields[i] }
field_type := unsafe { FieldType(field.@type) }
field_types << field_type
match types[i] {
orm.type_string {
mysql_bind.buffer_type = C.MYSQL_TYPE_BLOB
mysql_bind.buffer_length = FieldType.type_blob.get_len()
string_binds_map[i] = mysql_bind
}
orm.time {
match unsafe { FieldType(f.@type) } {
match field_type {
.type_long {
mysql_bind.buffer_type = C.MYSQL_TYPE_LONG
}
@ -92,7 +90,7 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
}
.type_string, .type_blob {}
else {
return error('Unknown type ${f.@type}')
return error('Unknown type ${field.@type}')
}
}
}
@ -102,13 +100,23 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
stmt.bind_result_buffer()!
stmt.store_result()!
for {
status = stmt.fetch_stmt()!
if status == 1 || status == 100 {
break
}
row++
for index, mut bind in string_binds_map {
string_length := lengths[index] + 1
dataptr[index] = unsafe { malloc(string_length) }
bind.buffer = dataptr[index]
bind.buffer_length = string_length
bind.length = unsafe { nil }
stmt.fetch_column(bind, index)!
}
data_list := buffer_to_primitive(dataptr, types, field_types)!
ret << data_list