reifydb_client/
session.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the MIT
3
4use reifydb_type::{
5	BitVec, Blob, Date, DateTime, Error, Frame, FrameColumn, FrameColumnData, IdentityId, OwnedFragment, RowNumber,
6	Time, Uuid7, err, parse_datetime, parse_uuid4, parse_uuid7,
7	util::hex,
8	value::container::{
9		BlobContainer, BoolContainer, IdentityIdContainer, NumberContainer, RowNumberContainer,
10		TemporalContainer, UndefinedContainer, Utf8Container, UuidContainer,
11	},
12};
13
14use crate::Type;
15
16/// Result type for command operations
17#[derive(Debug)]
18pub struct CommandResult {
19	pub frames: Vec<Frame>,
20}
21
22/// Result type for query operations
23#[derive(Debug)]
24pub struct QueryResult {
25	pub frames: Vec<Frame>,
26}
27
28// Helper functions for parsing responses - made public for ws module
29pub fn parse_command_response(response: crate::Response) -> Result<CommandResult, Error> {
30	match response.payload {
31		crate::ResponsePayload::Command(cmd_response) => Ok(CommandResult {
32			frames: convert_command_response(cmd_response),
33		}),
34		crate::ResponsePayload::Err(err) => {
35			err!(err.diagnostic)
36		}
37		other => {
38			println!("Unexpected execute response: {:?}", other);
39			panic!("Unexpected execute response type")
40		}
41	}
42}
43
44pub fn parse_query_response(response: crate::Response) -> Result<QueryResult, Error> {
45	match response.payload {
46		crate::ResponsePayload::Query(query_response) => {
47			let frames = convert_query_response(query_response);
48			Ok(QueryResult {
49				frames,
50			})
51		}
52		crate::ResponsePayload::Err(err) => {
53			err!(err.diagnostic)
54		}
55		other => {
56			println!("Unexpected execute response: {:?}", other);
57			panic!("Unexpected execute response type")
58		}
59	}
60}
61
62pub fn convert_command_response(payload: crate::CommandResponse) -> Vec<Frame> {
63	let mut result = Vec::new();
64
65	for frame in payload.frames {
66		let columns = frame
67			.columns
68			.into_iter()
69			.map(|col| FrameColumn {
70				namespace: col.namespace,
71				source: col.store,
72				name: col.name,
73				data: convert_column_to_data(col.r#type, col.data),
74			})
75			.collect();
76
77		let row_numbers = frame.row_numbers.into_iter().map(RowNumber::new).collect();
78		result.push(Frame::with_row_numbers(columns, row_numbers))
79	}
80
81	result
82}
83
84pub fn convert_query_response(payload: crate::QueryResponse) -> Vec<Frame> {
85	let mut result = Vec::new();
86
87	for frame in payload.frames {
88		let columns = frame
89			.columns
90			.into_iter()
91			.map(|col| FrameColumn {
92				namespace: col.namespace,
93				source: col.store,
94				name: col.name,
95				data: convert_column_to_data(col.r#type, col.data),
96			})
97			.collect();
98
99		let row_numbers = frame.row_numbers.into_iter().map(RowNumber::new).collect();
100		result.push(Frame::with_row_numbers(columns, row_numbers))
101	}
102
103	result
104}
105
106fn convert_column_to_data(target: Type, data: Vec<String>) -> FrameColumnData {
107	let len = data.len();
108
109	match target {
110		Type::Undefined => FrameColumnData::Undefined(UndefinedContainer::new(len)),
111		Type::Boolean => {
112			let (values, defined): (Vec<_>, Vec<_>) = data
113				.into_iter()
114				.map(|s| {
115					if s == "⟪undefined⟫" {
116						(false, false)
117					} else {
118						(s == "true", true)
119					}
120				})
121				.unzip();
122			FrameColumnData::Bool(BoolContainer::new(values, BitVec::from_slice(&defined)))
123		}
124		Type::Float4 => {
125			let (values, defined): (Vec<_>, Vec<_>) = data
126				.into_iter()
127				.map(|s| {
128					if s == "⟪undefined⟫" {
129						(0.0f32, false)
130					} else {
131						(s.parse::<f32>().unwrap_or(0.0), true)
132					}
133				})
134				.unzip();
135			FrameColumnData::Float4(NumberContainer::new(values, BitVec::from_slice(&defined)))
136		}
137		Type::Float8 => {
138			let (values, defined): (Vec<_>, Vec<_>) = data
139				.into_iter()
140				.map(|s| {
141					if s == "⟪undefined⟫" {
142						(0.0f64, false)
143					} else {
144						(s.parse::<f64>().unwrap_or(0.0), true)
145					}
146				})
147				.unzip();
148			FrameColumnData::Float8(NumberContainer::new(values, BitVec::from_slice(&defined)))
149		}
150		Type::Int1 => {
151			let (values, defined): (Vec<_>, Vec<_>) = data
152				.into_iter()
153				.map(|s| {
154					if s == "⟪undefined⟫" {
155						(0i8, false)
156					} else {
157						(s.parse::<i8>().unwrap_or(0), true)
158					}
159				})
160				.unzip();
161			FrameColumnData::Int1(NumberContainer::new(values, BitVec::from_slice(&defined)))
162		}
163		Type::Int2 => {
164			let (values, defined): (Vec<_>, Vec<_>) = data
165				.into_iter()
166				.map(|s| {
167					if s == "⟪undefined⟫" {
168						(0i16, false)
169					} else {
170						(s.parse::<i16>().unwrap_or(0), true)
171					}
172				})
173				.unzip();
174			FrameColumnData::Int2(NumberContainer::new(values, BitVec::from_slice(&defined)))
175		}
176		Type::Int4 => {
177			let (values, defined): (Vec<_>, Vec<_>) = data
178				.into_iter()
179				.map(|s| {
180					if s == "⟪undefined⟫" {
181						(0i32, false)
182					} else {
183						(s.parse::<i32>().unwrap_or(0), true)
184					}
185				})
186				.unzip();
187			FrameColumnData::Int4(NumberContainer::new(values, BitVec::from_slice(&defined)))
188		}
189		Type::Int8 => {
190			let (values, defined): (Vec<_>, Vec<_>) = data
191				.into_iter()
192				.map(|s| {
193					if s == "⟪undefined⟫" {
194						(0i64, false)
195					} else {
196						(s.parse::<i64>().unwrap_or(0), true)
197					}
198				})
199				.unzip();
200			FrameColumnData::Int8(NumberContainer::new(values, BitVec::from_slice(&defined)))
201		}
202		Type::Int16 => {
203			let (values, defined): (Vec<_>, Vec<_>) = data
204				.into_iter()
205				.map(|s| {
206					if s == "⟪undefined⟫" {
207						(0i128, false)
208					} else {
209						(s.parse::<i128>().unwrap_or(0), true)
210					}
211				})
212				.unzip();
213			FrameColumnData::Int16(NumberContainer::new(values, BitVec::from_slice(&defined)))
214		}
215		Type::Uint1 => {
216			let (values, defined): (Vec<_>, Vec<_>) = data
217				.into_iter()
218				.map(|s| {
219					if s == "⟪undefined⟫" {
220						(0u8, false)
221					} else {
222						(s.parse::<u8>().unwrap_or(0), true)
223					}
224				})
225				.unzip();
226			FrameColumnData::Uint1(NumberContainer::new(values, BitVec::from_slice(&defined)))
227		}
228		Type::Uint2 => {
229			let (values, defined): (Vec<_>, Vec<_>) = data
230				.into_iter()
231				.map(|s| {
232					if s == "⟪undefined⟫" {
233						(0u16, false)
234					} else {
235						(s.parse::<u16>().unwrap_or(0), true)
236					}
237				})
238				.unzip();
239			FrameColumnData::Uint2(NumberContainer::new(values, BitVec::from_slice(&defined)))
240		}
241		Type::Uint4 => {
242			let (values, defined): (Vec<_>, Vec<_>) = data
243				.into_iter()
244				.map(|s| {
245					if s == "⟪undefined⟫" {
246						(0u32, false)
247					} else {
248						(s.parse::<u32>().unwrap_or(0), true)
249					}
250				})
251				.unzip();
252			FrameColumnData::Uint4(NumberContainer::new(values, BitVec::from_slice(&defined)))
253		}
254		Type::Uint8 => {
255			let (values, defined): (Vec<_>, Vec<_>) = data
256				.into_iter()
257				.map(|s| {
258					if s == "⟪undefined⟫" {
259						(0u64, false)
260					} else {
261						(s.parse::<u64>().unwrap_or(0), true)
262					}
263				})
264				.unzip();
265			FrameColumnData::Uint8(NumberContainer::new(values, BitVec::from_slice(&defined)))
266		}
267		Type::Uint16 => {
268			let (values, defined): (Vec<_>, Vec<_>) = data
269				.into_iter()
270				.map(|s| {
271					if s == "⟪undefined⟫" {
272						(0u128, false)
273					} else {
274						(s.parse::<u128>().unwrap_or(0), true)
275					}
276				})
277				.unzip();
278			FrameColumnData::Uint16(NumberContainer::new(values, BitVec::from_slice(&defined)))
279		}
280		Type::Utf8 => {
281			let (values, defined): (Vec<_>, Vec<_>) = data
282				.into_iter()
283				.map(|s| {
284					if s == "⟪undefined⟫" {
285						(String::new(), false)
286					} else {
287						(s, true)
288					}
289				})
290				.unzip();
291			FrameColumnData::Utf8(Utf8Container::new(values, BitVec::from_slice(&defined)))
292		}
293		Type::Date => {
294			let (values, defined): (Vec<_>, Vec<_>) = data
295				.into_iter()
296				.map(|s| {
297					if s == "⟪undefined⟫" {
298						(Date::from_ymd(1970, 1, 1).unwrap(), false)
299					} else {
300						let parts: Vec<&str> = s.split('-').collect();
301						if parts.len() == 3 {
302							let year = parts[0].parse::<i32>().unwrap_or(1970);
303							let month = parts[1].parse::<u32>().unwrap_or(1);
304							let day = parts[2].parse::<u32>().unwrap_or(1);
305							(
306								Date::from_ymd(year, month, day)
307									.unwrap_or(Date::from_ymd(1970, 1, 1).unwrap()),
308								true,
309							)
310						} else {
311							(Date::from_ymd(1970, 1, 1).unwrap(), false)
312						}
313					}
314				})
315				.unzip();
316			FrameColumnData::Date(TemporalContainer::new(values, BitVec::from_slice(&defined)))
317		}
318		Type::DateTime => {
319			let (values, defined): (Vec<_>, Vec<_>) = data
320				.into_iter()
321				.map(|s| {
322					if s == "⟪undefined⟫" {
323						(DateTime::from_timestamp(0).unwrap(), false)
324					} else if let Ok(dt) = parse_datetime(OwnedFragment::testing(&s)) {
325						(dt, true)
326					} else if let Ok(timestamp) = s.parse::<i64>() {
327						(
328							DateTime::from_timestamp(timestamp)
329								.unwrap_or(DateTime::from_timestamp(0).unwrap()),
330							true,
331						)
332					} else {
333						(DateTime::from_timestamp(0).unwrap(), false)
334					}
335				})
336				.unzip();
337			FrameColumnData::DateTime(TemporalContainer::new(values, BitVec::from_slice(&defined)))
338		}
339		Type::Time => {
340			let (values, defined): (Vec<_>, Vec<_>) = data
341				.into_iter()
342				.map(|s| {
343					if s == "⟪undefined⟫" {
344						(Time::from_hms(0, 0, 0).unwrap(), false)
345					} else {
346						let parts: Vec<&str> = s.split(':').collect();
347						if parts.len() >= 3 {
348							let hour = parts[0].parse::<u32>().unwrap_or(0);
349							let min = parts[1].parse::<u32>().unwrap_or(0);
350							let sec_parts: Vec<&str> = parts[2].split('.').collect();
351							let sec = sec_parts[0].parse::<u32>().unwrap_or(0);
352							let nano = if sec_parts.len() > 1 {
353								let frac_str = sec_parts[1];
354								let padded = if frac_str.len() < 9 {
355									format!("{:0<9}", frac_str)
356								} else {
357									frac_str[..9].to_string()
358								};
359								padded.parse::<u32>().unwrap_or(0)
360							} else {
361								0
362							};
363							(
364								Time::from_hms_nano(hour, min, sec, nano)
365									.unwrap_or(Time::from_hms(0, 0, 0).unwrap()),
366								true,
367							)
368						} else {
369							(Time::from_hms(0, 0, 0).unwrap(), false)
370						}
371					}
372				})
373				.unzip();
374			FrameColumnData::Time(TemporalContainer::new(values, BitVec::from_slice(&defined)))
375		}
376		Type::Duration => {
377			// For Duration, store as Utf8 for now (needs proper ISO 8601 parsing)
378			let (values, defined): (Vec<_>, Vec<_>) = data
379				.into_iter()
380				.map(|s| {
381					if s == "⟪undefined⟫" {
382						(String::new(), false)
383					} else {
384						(s, true)
385					}
386				})
387				.unzip();
388			FrameColumnData::Utf8(Utf8Container::new(values, BitVec::from_slice(&defined)))
389		}
390		Type::RowNumber => {
391			let (values, defined): (Vec<_>, Vec<_>) = data
392				.into_iter()
393				.map(|s| {
394					if s == "⟪undefined⟫" {
395						(RowNumber::new(0), false)
396					} else {
397						(RowNumber::new(s.parse::<u64>().unwrap_or(0)), true)
398					}
399				})
400				.unzip();
401			FrameColumnData::RowNumber(RowNumberContainer::new(values, BitVec::from_slice(&defined)))
402		}
403		Type::Uuid4 => {
404			let (values, defined): (Vec<_>, Vec<_>) = data
405				.into_iter()
406				.map(|s| {
407					if s == "⟪undefined⟫" {
408						(parse_uuid4("00000000-0000-0000-0000-000000000000").unwrap(), false)
409					} else if let Ok(uuid) = parse_uuid4(&s) {
410						(uuid, true)
411					} else {
412						(parse_uuid4("00000000-0000-0000-0000-000000000000").unwrap(), false)
413					}
414				})
415				.unzip();
416			FrameColumnData::Uuid4(UuidContainer::new(values, BitVec::from_slice(&defined)))
417		}
418		Type::Uuid7 => {
419			let (values, defined): (Vec<_>, Vec<_>) = data
420				.into_iter()
421				.map(|s| {
422					if s == "⟪undefined⟫" {
423						(parse_uuid7("00000000-0000-7000-8000-000000000000").unwrap(), false)
424					} else if let Ok(uuid) = parse_uuid7(&s) {
425						(uuid, true)
426					} else {
427						(parse_uuid7("00000000-0000-7000-8000-000000000000").unwrap(), false)
428					}
429				})
430				.unzip();
431			FrameColumnData::Uuid7(UuidContainer::new(values, BitVec::from_slice(&defined)))
432		}
433		Type::IdentityId => {
434			let (values, defined): (Vec<_>, Vec<_>) = data
435				.into_iter()
436				.map(|s| {
437					if s == "⟪undefined⟫" {
438						(
439							IdentityId::from(Uuid7::from(
440								parse_uuid7("00000000-0000-7000-8000-000000000000")
441									.unwrap(),
442							)),
443							false,
444						)
445					} else if let Ok(uuid) = parse_uuid7(&s) {
446						(IdentityId::from(Uuid7::from(uuid)), true)
447					} else {
448						(
449							IdentityId::from(Uuid7::from(
450								parse_uuid7("00000000-0000-7000-8000-000000000000")
451									.unwrap(),
452							)),
453							false,
454						)
455					}
456				})
457				.unzip();
458			FrameColumnData::IdentityId(IdentityIdContainer::new(values, BitVec::from_slice(&defined)))
459		}
460		Type::Blob => {
461			let (values, defined): (Vec<_>, Vec<_>) = data
462				.into_iter()
463				.map(|s| {
464					if s == "⟪undefined⟫" {
465						(Blob::new(vec![]), false)
466					} else if s.starts_with("0x") {
467						if let Ok(bytes) = hex::decode(&s[2..]) {
468							(Blob::new(bytes), true)
469						} else {
470							(Blob::new(vec![]), false)
471						}
472					} else {
473						(Blob::new(vec![]), false)
474					}
475				})
476				.unzip();
477			FrameColumnData::Blob(BlobContainer::new(values, BitVec::from_slice(&defined)))
478		}
479		Type::Int
480		| Type::Uint
481		| Type::Decimal {
482			..
483		}
484		| Type::Any => {
485			// For arbitrary-precision types and Any, store as Utf8
486			let (values, defined): (Vec<_>, Vec<_>) = data
487				.into_iter()
488				.map(|s| {
489					if s == "⟪undefined⟫" {
490						(String::new(), false)
491					} else {
492						(s, true)
493					}
494				})
495				.unzip();
496			FrameColumnData::Utf8(Utf8Container::new(values, BitVec::from_slice(&defined)))
497		}
498	}
499}