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, Fragment, Frame, FrameColumn, FrameColumnData, IdentityId, RowNumber,
6	Time, Uuid7, err, parse_datetime, parse_uuid4, parse_uuid7,
7	util::hex,
8	value::container::{
9		BlobContainer, BoolContainer, IdentityIdContainer, NumberContainer, TemporalContainer,
10		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(Fragment::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::Uuid4 => {
391			let (values, defined): (Vec<_>, Vec<_>) = data
392				.into_iter()
393				.map(|s| {
394					if s == "⟪undefined⟫" {
395						(
396							parse_uuid4("00000000-0000-0000-0000-000000000000".into())
397								.unwrap(),
398							false,
399						)
400					} else if let Ok(uuid) = parse_uuid4(s.into()) {
401						(uuid, true)
402					} else {
403						(
404							parse_uuid4("00000000-0000-0000-0000-000000000000".into())
405								.unwrap(),
406							false,
407						)
408					}
409				})
410				.unzip();
411			FrameColumnData::Uuid4(UuidContainer::new(values, BitVec::from_slice(&defined)))
412		}
413		Type::Uuid7 => {
414			let (values, defined): (Vec<_>, Vec<_>) = data
415				.into_iter()
416				.map(|s| {
417					if s == "⟪undefined⟫" {
418						(
419							parse_uuid7("00000000-0000-7000-8000-000000000000".into())
420								.unwrap(),
421							false,
422						)
423					} else if let Ok(uuid) = parse_uuid7(s.into()) {
424						(uuid, true)
425					} else {
426						(
427							parse_uuid7("00000000-0000-7000-8000-000000000000".into())
428								.unwrap(),
429							false,
430						)
431					}
432				})
433				.unzip();
434			FrameColumnData::Uuid7(UuidContainer::new(values, BitVec::from_slice(&defined)))
435		}
436		Type::IdentityId => {
437			let (values, defined): (Vec<_>, Vec<_>) = data
438				.into_iter()
439				.map(|s| {
440					if s == "⟪undefined⟫" {
441						(
442							IdentityId::from(Uuid7::from(
443								parse_uuid7(
444									"00000000-0000-7000-8000-000000000000".into(),
445								)
446								.unwrap(),
447							)),
448							false,
449						)
450					} else if let Ok(uuid) = parse_uuid7(s.into()) {
451						(IdentityId::from(Uuid7::from(uuid)), true)
452					} else {
453						(
454							IdentityId::from(Uuid7::from(
455								parse_uuid7(
456									"00000000-0000-7000-8000-000000000000".into(),
457								)
458								.unwrap(),
459							)),
460							false,
461						)
462					}
463				})
464				.unzip();
465			FrameColumnData::IdentityId(IdentityIdContainer::new(values, BitVec::from_slice(&defined)))
466		}
467		Type::Blob => {
468			let (values, defined): (Vec<_>, Vec<_>) = data
469				.into_iter()
470				.map(|s| {
471					if s == "⟪undefined⟫" {
472						(Blob::new(vec![]), false)
473					} else if s.starts_with("0x") {
474						if let Ok(bytes) = hex::decode(&s[2..]) {
475							(Blob::new(bytes), true)
476						} else {
477							(Blob::new(vec![]), false)
478						}
479					} else {
480						(Blob::new(vec![]), false)
481					}
482				})
483				.unzip();
484			FrameColumnData::Blob(BlobContainer::new(values, BitVec::from_slice(&defined)))
485		}
486		Type::Int
487		| Type::Uint
488		| Type::Decimal {
489			..
490		}
491		| Type::Any => {
492			// For arbitrary-precision types and Any, store as Utf8
493			let (values, defined): (Vec<_>, Vec<_>) = data
494				.into_iter()
495				.map(|s| {
496					if s == "⟪undefined⟫" {
497						(String::new(), false)
498					} else {
499						(s, true)
500					}
501				})
502				.unzip();
503			FrameColumnData::Utf8(Utf8Container::new(values, BitVec::from_slice(&defined)))
504		}
505	}
506}