11use crate :: error:: Error ;
22use crate :: odbc:: {
3- connection:: MaybePrepared , OdbcArgumentValue , OdbcArguments , OdbcColumn , OdbcQueryResult ,
4- OdbcRow , OdbcTypeInfo , OdbcValue ,
3+ connection:: MaybePrepared , ColumnData , OdbcArgumentValue , OdbcArguments , OdbcColumn ,
4+ OdbcQueryResult , OdbcRow , OdbcTypeInfo , OdbcValue ,
55} ;
66use either:: Either ;
77use flume:: { SendError , Sender } ;
@@ -10,6 +10,7 @@ use odbc_api::handles::{AsStatementRef, Nullability, Statement};
1010use odbc_api:: DataType ;
1111use odbc_api:: { Cursor , IntoParameter , ResultSetMetadata } ;
1212use std:: cmp:: min;
13+ use std:: sync:: Arc ;
1314
1415// Bulk fetch implementation using columnar buffers instead of row-by-row fetching
1516// This provides significant performance improvements by fetching rows in batches
@@ -18,8 +19,8 @@ const BATCH_SIZE: usize = 128;
1819const DEFAULT_TEXT_LEN : usize = 512 ;
1920const DEFAULT_BINARY_LEN : usize = 1024 ;
2021const DEFAULT_NUMERIC_TEXT_LEN : usize = 128 ;
21- const MAX_TEXT_LEN : usize = 1024 * 1024 ;
22- const MAX_BINARY_LEN : usize = 1024 * 1024 ;
22+ const MAX_TEXT_LEN : usize = 1024 ;
23+ const MAX_BINARY_LEN : usize = 1024 ;
2324
2425struct ColumnBinding {
2526 column : OdbcColumn ,
@@ -238,21 +239,24 @@ where
238239 while let Some ( batch) = row_set_cursor. fetch ( ) ? {
239240 let columns: Vec < _ > = bindings. iter ( ) . map ( |b| b. column . clone ( ) ) . collect ( ) ;
240241
242+ // Create ColumnData instances that can be shared across rows
243+ let column_data_vec: Vec < _ > = bindings
244+ . iter ( )
245+ . enumerate ( )
246+ . map ( |( col_index, binding) | {
247+ create_column_data ( batch. column ( col_index) , & binding. column . type_info )
248+ } )
249+ . collect ( ) ;
250+
241251 for row_index in 0 ..batch. num_rows ( ) {
242- let row_values: Vec < _ > = bindings
252+ let row_values: Vec < _ > = column_data_vec
243253 . iter ( )
244- . enumerate ( )
245- . map ( |( col_index, binding) | {
246- let type_info = binding. column . type_info . clone ( ) ;
247- let value =
248- extract_value_from_buffer ( batch. column ( col_index) , row_index, & type_info) ;
249- ( type_info, value)
250- } )
254+ . map ( |column_data| OdbcValue :: new ( Arc :: clone ( column_data) , row_index) )
251255 . collect ( ) ;
252256
253257 let row = OdbcRow {
254258 columns : columns. clone ( ) ,
255- values : row_values. into_iter ( ) . map ( | ( _ , value ) | value ) . collect ( ) ,
259+ values : row_values,
256260 } ;
257261
258262 if send_row ( tx, row) . is_err ( ) {
@@ -269,237 +273,11 @@ where
269273 Ok ( receiver_open)
270274}
271275
272- fn extract_value_from_buffer (
273- slice : AnySlice < ' _ > ,
274- row_index : usize ,
275- type_info : & OdbcTypeInfo ,
276- ) -> OdbcValue {
277- match slice {
278- AnySlice :: I8 ( s) => OdbcValue {
279- type_info : type_info. clone ( ) ,
280- is_null : false ,
281- text : None ,
282- blob : None ,
283- int : Some ( s[ row_index] as i64 ) ,
284- float : None ,
285- } ,
286- AnySlice :: I16 ( s) => OdbcValue {
287- type_info : type_info. clone ( ) ,
288- is_null : false ,
289- text : None ,
290- blob : None ,
291- int : Some ( s[ row_index] as i64 ) ,
292- float : None ,
293- } ,
294- AnySlice :: I32 ( s) => OdbcValue {
295- type_info : type_info. clone ( ) ,
296- is_null : false ,
297- text : None ,
298- blob : None ,
299- int : Some ( s[ row_index] as i64 ) ,
300- float : None ,
301- } ,
302- AnySlice :: I64 ( s) => OdbcValue {
303- type_info : type_info. clone ( ) ,
304- is_null : false ,
305- text : None ,
306- blob : None ,
307- int : Some ( s[ row_index] ) ,
308- float : None ,
309- } ,
310- AnySlice :: F32 ( s) => OdbcValue {
311- type_info : type_info. clone ( ) ,
312- is_null : false ,
313- text : None ,
314- blob : None ,
315- int : None ,
316- float : Some ( s[ row_index] as f64 ) ,
317- } ,
318- AnySlice :: F64 ( s) => OdbcValue {
319- type_info : type_info. clone ( ) ,
320- is_null : false ,
321- text : None ,
322- blob : None ,
323- int : None ,
324- float : Some ( s[ row_index] ) ,
325- } ,
326- AnySlice :: Bit ( s) => OdbcValue {
327- type_info : type_info. clone ( ) ,
328- is_null : false ,
329- text : None ,
330- blob : None ,
331- int : Some ( s[ row_index] . 0 as i64 ) ,
332- float : None ,
333- } ,
334- AnySlice :: Text ( s) => {
335- let text = s
336- . get ( row_index)
337- . map ( |bytes| String :: from_utf8_lossy ( bytes) . to_string ( ) ) ;
338- OdbcValue {
339- type_info : type_info. clone ( ) ,
340- is_null : text. is_none ( ) ,
341- text,
342- blob : None ,
343- int : None ,
344- float : None ,
345- }
346- }
347- AnySlice :: Binary ( s) => {
348- let blob = s. get ( row_index) . map ( |bytes| bytes. to_vec ( ) ) ;
349- OdbcValue {
350- type_info : type_info. clone ( ) ,
351- is_null : blob. is_none ( ) ,
352- text : None ,
353- blob,
354- int : None ,
355- float : None ,
356- }
357- }
358- AnySlice :: NullableI8 ( s) => {
359- let ( is_null, int) = if let Some ( & val) = s. get ( row_index) {
360- ( false , Some ( val as i64 ) )
361- } else {
362- ( true , None )
363- } ;
364- OdbcValue {
365- type_info : type_info. clone ( ) ,
366- is_null,
367- text : None ,
368- blob : None ,
369- int,
370- float : None ,
371- }
372- }
373- AnySlice :: NullableI16 ( s) => {
374- let ( is_null, int) = if let Some ( & val) = s. get ( row_index) {
375- ( false , Some ( val as i64 ) )
376- } else {
377- ( true , None )
378- } ;
379- OdbcValue {
380- type_info : type_info. clone ( ) ,
381- is_null,
382- text : None ,
383- blob : None ,
384- int,
385- float : None ,
386- }
387- }
388- AnySlice :: NullableI32 ( s) => {
389- let ( is_null, int) = if let Some ( & val) = s. get ( row_index) {
390- ( false , Some ( val as i64 ) )
391- } else {
392- ( true , None )
393- } ;
394- OdbcValue {
395- type_info : type_info. clone ( ) ,
396- is_null,
397- text : None ,
398- blob : None ,
399- int,
400- float : None ,
401- }
402- }
403- AnySlice :: NullableI64 ( s) => {
404- let ( is_null, int) = if let Some ( & val) = s. get ( row_index) {
405- ( false , Some ( val) )
406- } else {
407- ( true , None )
408- } ;
409- OdbcValue {
410- type_info : type_info. clone ( ) ,
411- is_null,
412- text : None ,
413- blob : None ,
414- int,
415- float : None ,
416- }
417- }
418- AnySlice :: NullableF32 ( s) => {
419- let ( is_null, float) = if let Some ( & val) = s. get ( row_index) {
420- ( false , Some ( val as f64 ) )
421- } else {
422- ( true , None )
423- } ;
424- OdbcValue {
425- type_info : type_info. clone ( ) ,
426- is_null,
427- text : None ,
428- blob : None ,
429- int : None ,
430- float,
431- }
432- }
433- AnySlice :: NullableF64 ( s) => {
434- let ( is_null, float) = if let Some ( & val) = s. get ( row_index) {
435- ( false , Some ( val) )
436- } else {
437- ( true , None )
438- } ;
439- OdbcValue {
440- type_info : type_info. clone ( ) ,
441- is_null,
442- text : None ,
443- blob : None ,
444- int : None ,
445- float,
446- }
447- }
448- AnySlice :: NullableBit ( s) => {
449- let ( is_null, int) = if let Some ( & val) = s. get ( row_index) {
450- ( false , Some ( val. 0 as i64 ) )
451- } else {
452- ( true , None )
453- } ;
454- OdbcValue {
455- type_info : type_info. clone ( ) ,
456- is_null,
457- text : None ,
458- blob : None ,
459- int,
460- float : None ,
461- }
462- }
463- AnySlice :: Date ( s) => {
464- let text = s. get ( row_index) . map ( |date| format ! ( "{:?}" , date) ) ;
465- OdbcValue {
466- type_info : type_info. clone ( ) ,
467- is_null : text. is_none ( ) ,
468- text,
469- blob : None ,
470- int : None ,
471- float : None ,
472- }
473- }
474- AnySlice :: Time ( s) => {
475- let text = s. get ( row_index) . map ( |time| format ! ( "{:?}" , time) ) ;
476- OdbcValue {
477- type_info : type_info. clone ( ) ,
478- is_null : text. is_none ( ) ,
479- text,
480- blob : None ,
481- int : None ,
482- float : None ,
483- }
484- }
485- AnySlice :: Timestamp ( s) => {
486- let text = s. get ( row_index) . map ( |ts| format ! ( "{:?}" , ts) ) ;
487- OdbcValue {
488- type_info : type_info. clone ( ) ,
489- is_null : text. is_none ( ) ,
490- text,
491- blob : None ,
492- int : None ,
493- float : None ,
494- }
495- }
496- _ => OdbcValue {
497- type_info : type_info. clone ( ) ,
498- is_null : true ,
499- text : None ,
500- blob : None ,
501- int : None ,
502- float : None ,
503- } ,
504- }
276+ fn create_column_data ( slice : AnySlice < ' _ > , type_info : & OdbcTypeInfo ) -> Arc < ColumnData > {
277+ use crate :: odbc:: value:: convert_any_slice_to_value_vec;
278+
279+ Arc :: new ( ColumnData {
280+ values : convert_any_slice_to_value_vec ( slice) ,
281+ type_info : type_info. clone ( ) ,
282+ } )
505283}
0 commit comments