1use std::sync::atomic::AtomicI64;
2
3#[cfg(feature = "with_chrono")]
4use {chrono::Datelike, chrono::Offset};
5
6#[cfg(any(feature = "with_bigdecimal", feature = "with_rust_decimal"))]
7use crate::jogasaki::proto::sql::common::Decimal as ProtoDecimal;
8#[cfg(any(feature = "with_chrono", feature = "with_time"))]
9use crate::jogasaki::proto::sql::common::{
10 TimeOfDayWithTimeZone as ProtoTimeOfDayWithTimeZone, TimePoint as ProtoTimePoint,
11 TimePointWithTimeZone as ProtoTimePointWithTimeZone,
12};
13use crate::jogasaki::proto::sql::request::parameter::{Placement, Value};
14use crate::prelude::{
15 r#type::large_object::LargeObjectSendPathMapping, TgBlob, TgClob, TgDate, TgDecimal,
16 TgDecimalI128, TgTimeOfDay, TgTimeOfDayWithTimeZone, TgTimePoint, TgTimePointWithTimeZone,
17};
18use crate::tateyama::proto::framework::common::BlobInfo;
19use crate::{error::TgError, jogasaki::proto::sql::request::Parameter as SqlParameter};
20
21impl SqlParameter {
22 fn new(name: &str, value: Option<Value>) -> SqlParameter {
23 let placement = Placement::Name(name.to_string());
24
25 SqlParameter {
26 placement: Some(placement),
27 value,
28 }
29 }
30
31 pub fn null(name: &str) -> SqlParameter {
33 SqlParameter::new(name, None)
34 }
35
36 pub fn name(&self) -> Option<&String> {
38 match self.placement {
39 Some(Placement::Name(ref name)) => Some(name),
40 _ => None,
41 }
42 }
43
44 pub fn value(&self) -> Option<&Value> {
46 self.value.as_ref()
47 }
48}
49
50pub trait SqlParameterOf<T> {
52 fn of(name: &str, value: T) -> SqlParameter;
54}
55
56impl SqlParameterOf<bool> for SqlParameter {
57 fn of(name: &str, value: bool) -> SqlParameter {
58 let value = Value::BooleanValue(value);
59 SqlParameter::new(name, Some(value))
60 }
61}
62
63impl SqlParameterOf<i32> for SqlParameter {
64 fn of(name: &str, value: i32) -> SqlParameter {
65 let value = Value::Int4Value(value);
66 SqlParameter::new(name, Some(value))
67 }
68}
69
70impl SqlParameterOf<i64> for SqlParameter {
71 fn of(name: &str, value: i64) -> SqlParameter {
72 let value = Value::Int8Value(value);
73 SqlParameter::new(name, Some(value))
74 }
75}
76
77impl SqlParameterOf<f32> for SqlParameter {
78 fn of(name: &str, value: f32) -> SqlParameter {
79 let value = Value::Float4Value(value);
80 SqlParameter::new(name, Some(value))
81 }
82}
83
84impl SqlParameterOf<f64> for SqlParameter {
85 fn of(name: &str, value: f64) -> SqlParameter {
86 let value = Value::Float8Value(value);
87 SqlParameter::new(name, Some(value))
88 }
89}
90
91impl SqlParameterOf<TgDecimal> for SqlParameter {
92 fn of(name: &str, value: TgDecimal) -> SqlParameter {
93 let value = Value::DecimalValue(value);
94 SqlParameter::new(name, Some(value))
95 }
96}
97
98impl SqlParameterOf<TgDecimalI128> for SqlParameter {
99 fn of(name: &str, value: TgDecimalI128) -> SqlParameter {
100 let value = TgDecimal::from(value);
101 Self::of(name, value)
102 }
103}
104
105#[cfg(feature = "with_bigdecimal")]
106impl SqlParameterOf<bigdecimal::BigDecimal> for SqlParameter {
107 fn of(name: &str, value: bigdecimal::BigDecimal) -> SqlParameter {
108 Self::of(name, &value)
109 }
110}
111
112#[cfg(feature = "with_bigdecimal")]
113impl SqlParameterOf<&bigdecimal::BigDecimal> for SqlParameter {
114 fn of(name: &str, value: &bigdecimal::BigDecimal) -> SqlParameter {
115 let (value, scale) = value.as_bigint_and_exponent();
116 let value = ProtoDecimal {
117 unscaled_value: value.to_signed_bytes_be(),
118 exponent: -scale as i32,
119 };
120 let value = Value::DecimalValue(value);
121 SqlParameter::new(name, Some(value))
122 }
123}
124
125#[cfg(feature = "with_rust_decimal")]
126impl SqlParameterOf<rust_decimal::Decimal> for SqlParameter {
127 fn of(name: &str, value: rust_decimal::Decimal) -> SqlParameter {
128 Self::of(name, &value)
129 }
130}
131
132#[cfg(feature = "with_rust_decimal")]
133impl SqlParameterOf<&rust_decimal::Decimal> for SqlParameter {
134 fn of(name: &str, value: &rust_decimal::Decimal) -> SqlParameter {
135 let value = ProtoDecimal {
136 unscaled_value: value.mantissa().to_be_bytes().to_vec(),
137 exponent: -(value.scale() as i32),
138 };
139 let value = Value::DecimalValue(value);
140 SqlParameter::new(name, Some(value))
141 }
142}
143
144impl SqlParameterOf<&str> for SqlParameter {
145 fn of(name: &str, value: &str) -> SqlParameter {
146 let value = Value::CharacterValue(value.to_string());
147 SqlParameter::new(name, Some(value))
148 }
149}
150
151impl SqlParameterOf<String> for SqlParameter {
152 fn of(name: &str, value: String) -> SqlParameter {
153 let value = Value::CharacterValue(value);
154 SqlParameter::new(name, Some(value))
155 }
156}
157
158impl SqlParameterOf<&String> for SqlParameter {
159 fn of(name: &str, value: &String) -> SqlParameter {
160 let value = Value::CharacterValue(value.clone());
161 SqlParameter::new(name, Some(value))
162 }
163}
164
165impl SqlParameterOf<&[u8]> for SqlParameter {
166 fn of(name: &str, value: &[u8]) -> SqlParameter {
167 let value = Value::OctetValue(value.to_vec());
168 SqlParameter::new(name, Some(value))
169 }
170}
171
172impl SqlParameterOf<Vec<u8>> for SqlParameter {
173 fn of(name: &str, value: Vec<u8>) -> SqlParameter {
174 let value = Value::OctetValue(value);
175 SqlParameter::new(name, Some(value))
176 }
177}
178
179impl SqlParameterOf<&Vec<u8>> for SqlParameter {
180 fn of(name: &str, value: &Vec<u8>) -> SqlParameter {
181 let value = Value::OctetValue(value.clone());
182 SqlParameter::new(name, Some(value))
183 }
184}
185
186impl SqlParameterOf<TgDate> for SqlParameter {
187 fn of(name: &str, value: TgDate) -> SqlParameter {
188 let value = Value::DateValue(value.epoch_days);
189 SqlParameter::new(name, Some(value))
190 }
191}
192
193impl SqlParameterOf<TgTimeOfDay> for SqlParameter {
194 fn of(name: &str, value: TgTimeOfDay) -> SqlParameter {
195 let value = Value::TimeOfDayValue(value.offset_nanoseconds);
196 SqlParameter::new(name, Some(value))
197 }
198}
199
200impl SqlParameterOf<TgTimePoint> for SqlParameter {
201 fn of(name: &str, value: TgTimePoint) -> SqlParameter {
202 let value = Value::TimePointValue(value);
203 SqlParameter::new(name, Some(value))
204 }
205}
206
207impl SqlParameterOf<TgTimeOfDayWithTimeZone> for SqlParameter {
208 fn of(name: &str, value: TgTimeOfDayWithTimeZone) -> SqlParameter {
209 let value = Value::TimeOfDayWithTimeZoneValue(value);
210 SqlParameter::new(name, Some(value))
211 }
212}
213
214impl SqlParameterOf<TgTimePointWithTimeZone> for SqlParameter {
215 fn of(name: &str, value: TgTimePointWithTimeZone) -> SqlParameter {
216 let value = Value::TimePointWithTimeZoneValue(value);
217 SqlParameter::new(name, Some(value))
218 }
219}
220
221#[cfg(feature = "with_chrono")]
222impl SqlParameterOf<chrono::NaiveDate> for SqlParameter {
223 fn of(name: &str, value: chrono::NaiveDate) -> SqlParameter {
224 Self::of(name, &value)
225 }
226}
227
228#[cfg(feature = "with_chrono")]
229impl SqlParameterOf<&chrono::NaiveDate> for SqlParameter {
230 fn of(name: &str, value: &chrono::NaiveDate) -> SqlParameter {
231 let days = chrono_naive_date_to_days(value);
232
233 let value = Value::DateValue(days);
234 SqlParameter::new(name, Some(value))
235 }
236}
237
238#[cfg(feature = "with_chrono")]
239fn chrono_naive_date_to_days(value: &chrono::NaiveDate) -> i64 {
240 value.num_days_from_ce() as i64 - 719_163
241}
242
243#[cfg(feature = "with_chrono")]
244impl SqlParameterOf<chrono::NaiveTime> for SqlParameter {
245 fn of(name: &str, value: chrono::NaiveTime) -> SqlParameter {
246 Self::of(name, &value)
247 }
248}
249
250#[cfg(feature = "with_chrono")]
251impl SqlParameterOf<&chrono::NaiveTime> for SqlParameter {
252 fn of(name: &str, value: &chrono::NaiveTime) -> SqlParameter {
253 let (seconds, nanos) = chrono_naive_time_to_seconds(value);
254 let value = seconds * 1_000_000_000 + nanos as u64;
255
256 let value = Value::TimeOfDayValue(value);
257 SqlParameter::new(name, Some(value))
258 }
259}
260
261#[cfg(feature = "with_chrono")]
262fn chrono_naive_time_to_seconds(value: &chrono::NaiveTime) -> (u64, u32) {
263 use chrono::Timelike;
264
265 let seconds = value.num_seconds_from_midnight() as u64;
266 let nanos = value.nanosecond();
267
268 (seconds, nanos)
269}
270
271#[cfg(feature = "with_chrono")]
272impl SqlParameterOf<chrono::NaiveDateTime> for SqlParameter {
273 fn of(name: &str, value: chrono::NaiveDateTime) -> SqlParameter {
274 Self::of(name, &value)
275 }
276}
277
278#[cfg(feature = "with_chrono")]
279impl SqlParameterOf<&chrono::NaiveDateTime> for SqlParameter {
280 fn of(name: &str, value: &chrono::NaiveDateTime) -> SqlParameter {
281 let (seconds, nanos) = chrono_naive_date_time_to_seconds(value);
282
283 let value = ProtoTimePoint {
284 offset_seconds: seconds,
285 nano_adjustment: nanos,
286 };
287 let value = Value::TimePointValue(value);
288 SqlParameter::new(name, Some(value))
289 }
290}
291
292#[cfg(feature = "with_chrono")]
293fn chrono_naive_date_time_to_seconds(value: &chrono::NaiveDateTime) -> (i64, u32) {
294 let days = chrono_naive_date_to_days(&value.date());
295 let (seconds, nanos) = chrono_naive_time_to_seconds(&value.time());
296 let seconds = days * 24 * 60 * 60 + seconds as i64;
297
298 (seconds, nanos)
299}
300
301#[cfg(feature = "with_chrono")]
302impl SqlParameterOf<(chrono::NaiveTime, chrono::FixedOffset)> for SqlParameter {
303 fn of(name: &str, value: (chrono::NaiveTime, chrono::FixedOffset)) -> SqlParameter {
304 Self::of(name, &value)
305 }
306}
307
308#[cfg(feature = "with_chrono")]
309impl SqlParameterOf<&(chrono::NaiveTime, chrono::FixedOffset)> for SqlParameter {
310 fn of(name: &str, value: &(chrono::NaiveTime, chrono::FixedOffset)) -> SqlParameter {
311 let (time, offset) = value;
312
313 let (seconds, nanos) = chrono_naive_time_to_seconds(time);
314 let offset_minutes = chrono_fixed_offset_to_minutes(offset);
315
316 let value = ProtoTimeOfDayWithTimeZone {
317 offset_nanoseconds: seconds * 1_000_000_000 + nanos as u64,
318 time_zone_offset: offset_minutes,
319 };
320 let value = Value::TimeOfDayWithTimeZoneValue(value);
321 SqlParameter::new(name, Some(value))
322 }
323}
324
325#[cfg(feature = "with_chrono")]
326fn chrono_fixed_offset_to_minutes(value: &chrono::FixedOffset) -> i32 {
327 value.local_minus_utc() / 60
328}
329
330#[cfg(feature = "with_chrono")]
331impl<Tz: chrono::TimeZone> SqlParameterOf<chrono::DateTime<Tz>> for SqlParameter {
332 fn of(name: &str, value: chrono::DateTime<Tz>) -> SqlParameter {
333 Self::of(name, &value)
334 }
335}
336
337#[cfg(feature = "with_chrono")]
338impl<Tz: chrono::TimeZone> SqlParameterOf<&chrono::DateTime<Tz>> for SqlParameter {
339 fn of(name: &str, value: &chrono::DateTime<Tz>) -> SqlParameter {
340 let (seconds, nanos) = chrono_naive_date_time_to_seconds(&value.naive_local());
341 let offset_minutes = chrono_fixed_offset_to_minutes(&value.offset().fix());
342
343 let value = ProtoTimePointWithTimeZone {
344 offset_seconds: seconds,
345 nano_adjustment: nanos,
346 time_zone_offset: offset_minutes,
347 };
348 let value = Value::TimePointWithTimeZoneValue(value);
349 SqlParameter::new(name, Some(value))
350 }
351}
352
353#[cfg(feature = "with_time")]
354impl SqlParameterOf<time::Date> for SqlParameter {
355 fn of(name: &str, value: time::Date) -> SqlParameter {
356 Self::of(name, &value)
357 }
358}
359
360#[cfg(feature = "with_time")]
361impl SqlParameterOf<&time::Date> for SqlParameter {
362 fn of(name: &str, value: &time::Date) -> SqlParameter {
363 let days = time_date_to_days(value);
364
365 let value = Value::DateValue(days);
366 SqlParameter::new(name, Some(value))
367 }
368}
369
370#[cfg(feature = "with_time")]
375fn time_date_to_days(value: &time::Date) -> i64 {
376 value.to_julian_day() as i64 - 2440588
379}
380
381#[cfg(feature = "with_time")]
382impl SqlParameterOf<time::Time> for SqlParameter {
383 fn of(name: &str, value: time::Time) -> SqlParameter {
384 Self::of(name, &value)
385 }
386}
387
388#[cfg(feature = "with_time")]
389impl SqlParameterOf<&time::Time> for SqlParameter {
390 fn of(name: &str, value: &time::Time) -> SqlParameter {
391 let (seconds, nanos) = time_time_to_seconds(value);
392 let value = seconds * 1_000_000_000 + nanos as u64;
393
394 let value = Value::TimeOfDayValue(value);
395 SqlParameter::new(name, Some(value))
396 }
397}
398
399#[cfg(feature = "with_time")]
400fn time_time_to_seconds(value: &time::Time) -> (u64, u32) {
401 let (hour, min, sec, nanos) = value.as_hms_nano();
402 let seconds = ((hour as u64) * 60 + min as u64) * 60 + sec as u64;
403
404 (seconds, nanos)
405}
406
407#[cfg(feature = "with_time")]
408impl SqlParameterOf<time::PrimitiveDateTime> for SqlParameter {
409 fn of(name: &str, value: time::PrimitiveDateTime) -> SqlParameter {
410 Self::of(name, &value)
411 }
412}
413
414#[cfg(feature = "with_time")]
415impl SqlParameterOf<&time::PrimitiveDateTime> for SqlParameter {
416 fn of(name: &str, value: &time::PrimitiveDateTime) -> SqlParameter {
417 let (seconds, nanos) = time_date_time_to_seconds(&value.date(), &value.time());
418
419 let value = ProtoTimePoint {
420 offset_seconds: seconds,
421 nano_adjustment: nanos,
422 };
423 let value = Value::TimePointValue(value);
424 SqlParameter::new(name, Some(value))
425 }
426}
427
428#[cfg(feature = "with_time")]
429fn time_date_time_to_seconds(date: &time::Date, time: &time::Time) -> (i64, u32) {
430 let days = time_date_to_days(date);
431 let (seconds, nanos) = time_time_to_seconds(time);
432 let seconds = days * 24 * 60 * 60 + seconds as i64;
433
434 (seconds, nanos)
435}
436
437#[cfg(feature = "with_time")]
438impl SqlParameterOf<(time::Time, time::UtcOffset)> for SqlParameter {
439 fn of(name: &str, value: (time::Time, time::UtcOffset)) -> SqlParameter {
440 Self::of(name, &value)
441 }
442}
443
444#[cfg(feature = "with_time")]
445impl SqlParameterOf<&(time::Time, time::UtcOffset)> for SqlParameter {
446 fn of(name: &str, value: &(time::Time, time::UtcOffset)) -> SqlParameter {
447 let (time, offset) = value;
448
449 let (seconds, nanos) = time_time_to_seconds(time);
450 let offset_minutes = time_utc_offset_to_minutes(offset);
451
452 let value = ProtoTimeOfDayWithTimeZone {
453 offset_nanoseconds: seconds * 1_000_000_000 + nanos as u64,
454 time_zone_offset: offset_minutes,
455 };
456 let value = Value::TimeOfDayWithTimeZoneValue(value);
457 SqlParameter::new(name, Some(value))
458 }
459}
460
461#[cfg(feature = "with_time")]
462fn time_utc_offset_to_minutes(offset: &time::UtcOffset) -> i32 {
463 let (hour, min, _sec) = offset.as_hms();
464 hour as i32 * 60 + min as i32
465}
466
467#[cfg(feature = "with_time")]
468impl SqlParameterOf<time::OffsetDateTime> for SqlParameter {
469 fn of(name: &str, value: time::OffsetDateTime) -> SqlParameter {
470 Self::of(name, &value)
471 }
472}
473
474#[cfg(feature = "with_time")]
475impl SqlParameterOf<&time::OffsetDateTime> for SqlParameter {
476 fn of(name: &str, value: &time::OffsetDateTime) -> SqlParameter {
477 let (seconds, nanos) = time_date_time_to_seconds(&value.date(), &value.time());
478 let offset_minutes = time_utc_offset_to_minutes(&value.offset());
479
480 let value = ProtoTimePointWithTimeZone {
481 offset_seconds: seconds,
482 nano_adjustment: nanos,
483 time_zone_offset: offset_minutes,
484 };
485 let value = Value::TimePointWithTimeZoneValue(value);
486 SqlParameter::new(name, Some(value))
487 }
488}
489
490impl SqlParameterOf<TgBlob> for SqlParameter {
491 fn of(name: &str, value: TgBlob) -> SqlParameter {
492 use crate::jogasaki::proto::sql::common::blob::Data;
493 let data = match value {
494 TgBlob::Path(path) => Data::LocalPath(path),
495 TgBlob::Contents(value) => Data::Contents(value),
496 };
497 let value = crate::jogasaki::proto::sql::common::Blob { data: Some(data) };
498 let value = Value::Blob(value);
499 SqlParameter::new(name, Some(value))
500 }
501}
502
503impl SqlParameterOf<TgClob> for SqlParameter {
504 fn of(name: &str, value: TgClob) -> SqlParameter {
505 use crate::jogasaki::proto::sql::common::clob::Data;
506 let data = match value {
507 TgClob::Path(path) => Data::LocalPath(path),
508 TgClob::Contents(value) => Data::Contents(value),
509 };
510 let value = crate::jogasaki::proto::sql::common::Clob { data: Some(data) };
511 let value = Value::Clob(value);
512 SqlParameter::new(name, Some(value))
513 }
514}
515
516impl<T> SqlParameterOf<Option<T>> for SqlParameter
517where
518 SqlParameter: SqlParameterOf<T>,
519{
520 fn of(name: &str, value: Option<T>) -> SqlParameter {
521 match value {
522 Some(value) => SqlParameter::of(name, value),
523 _ => SqlParameter::null(name),
524 }
525 }
526}
527
528pub trait SqlParameterBind<T> {
530 fn parameter(&self, value: T) -> SqlParameter;
532}
533
534impl<T> SqlParameterBind<T> for &str
535where
536 SqlParameter: SqlParameterOf<T>,
537{
538 fn parameter(&self, value: T) -> SqlParameter {
539 SqlParameter::of(self, value)
540 }
541}
542
543impl<T> SqlParameterBind<T> for String
544where
545 SqlParameter: SqlParameterOf<T>,
546{
547 fn parameter(&self, value: T) -> SqlParameter {
548 SqlParameter::of(self, value)
549 }
550}
551
552pub trait SqlParameterBindNull {
554 fn parameter_null(&self) -> SqlParameter;
556}
557
558impl SqlParameterBindNull for &str {
559 fn parameter_null(&self) -> SqlParameter {
560 SqlParameter::null(self)
561 }
562}
563
564impl SqlParameterBindNull for String {
565 fn parameter_null(&self) -> SqlParameter {
566 SqlParameter::null(self)
567 }
568}
569
570static BLOB_NUMBER: AtomicI64 = AtomicI64::new(0);
571static CLOB_NUMBER: AtomicI64 = AtomicI64::new(0);
572
573pub(crate) fn convert_lob_parameters(
574 parameters: Vec<SqlParameter>,
575 lob_send_path_mapping: &LargeObjectSendPathMapping,
576) -> Result<(Vec<SqlParameter>, Option<Vec<BlobInfo>>), TgError> {
577 use crate::jogasaki::proto::sql::common::blob::Data as BlobData;
578 use crate::jogasaki::proto::sql::common::clob::Data as ClobData;
579 use crate::jogasaki::proto::sql::common::Blob;
580 use crate::jogasaki::proto::sql::common::Clob;
581
582 let mut parameters_result = Vec::with_capacity(parameters.len());
583 let mut lobs = Vec::new();
584 for parameter in parameters {
585 let parameter = match parameter {
586 SqlParameter {
587 placement,
588 value:
589 Some(Value::Blob(Blob {
590 data: Some(BlobData::LocalPath(path)),
591 })),
592 } => {
593 let path = lob_send_path_mapping.contert_to_server_path(&path)?;
594 let channel_name = create_channel_name("Blob", &BLOB_NUMBER);
595 let lob_info = BlobInfo {
596 channel_name: channel_name.clone(),
597 path,
598 temporary: false,
599 };
600 lobs.push(lob_info);
601
602 let data = BlobData::ChannelName(channel_name);
603 let value = Blob { data: Some(data) };
604 let value = Value::Blob(value);
605 SqlParameter {
606 placement,
607 value: Some(value),
608 }
609 }
610 SqlParameter {
611 placement,
612 value:
613 Some(Value::Clob(Clob {
614 data: Some(ClobData::LocalPath(path)),
615 })),
616 } => {
617 let path = lob_send_path_mapping.contert_to_server_path(&path)?;
618 let channel_name = create_channel_name("Clob", &CLOB_NUMBER);
619 let lob_info = BlobInfo {
621 channel_name: channel_name.clone(),
622 path,
623 temporary: false,
624 };
625 lobs.push(lob_info);
626
627 let data = ClobData::ChannelName(channel_name);
628 let value = Clob { data: Some(data) };
629 let value = Value::Clob(value);
630 SqlParameter {
631 placement,
632 value: Some(value),
633 }
634 }
635 parameter => parameter,
636 };
637 parameters_result.push(parameter);
638 }
639
640 if lobs.is_empty() {
641 Ok((parameters_result, None))
642 } else {
643 Ok((parameters_result, Some(lobs)))
644 }
645}
646
647fn create_channel_name(prefix: &str, number: &AtomicI64) -> String {
648 let pid = std::process::id();
649 let n = number.fetch_add(1, std::sync::atomic::Ordering::SeqCst) + 1;
650 format!("Rust{prefix}Channel-{pid}-{n}")
651}
652
653#[cfg(test)]
654mod test {
655 use super::*;
656
657 #[test]
658 fn null() {
659 let target0 = SqlParameter::null("test");
660 assert_eq!("test", target0.name().unwrap());
661 assert_eq!(None, target0.value);
662
663 let target = SqlParameter::of("test", None::<i32>);
664 assert_eq!(target0, target);
665
666 let target = "test".parameter_null();
667 assert_eq!(target0, target);
668
669 let target = "test".to_string().parameter_null();
670 assert_eq!(target0, target);
671 }
672
673 #[test]
674 fn bool() {
675 bool_test(true);
676 bool_test(false);
677 }
678
679 fn bool_test(value: bool) {
680 let target0 = SqlParameter::of("test", value);
681 assert_eq!("test", target0.name().unwrap());
682 assert_eq!(&Value::BooleanValue(value), target0.value().unwrap());
683
684 let target = SqlParameter::of("test", Some(value));
685 assert_eq!(target0, target);
686
687 let target = "test".parameter(value);
688 assert_eq!(target0, target);
689
690 let target = "test".to_string().parameter(value);
691 assert_eq!(target0, target);
692 }
693
694 #[test]
695 fn i32() {
696 let target0 = SqlParameter::of("test", 123);
697 assert_eq!("test", target0.name().unwrap());
698 assert_eq!(&Value::Int4Value(123), target0.value().unwrap());
699
700 let target = SqlParameter::of("test", Some(123));
701 assert_eq!(target0, target);
702
703 let target = "test".parameter(123);
704 assert_eq!(target0, target);
705
706 let target = "test".to_string().parameter(123);
707 assert_eq!(target0, target);
708 }
709
710 #[test]
711 fn i64() {
712 let target0 = SqlParameter::of("test", 123_i64);
713 assert_eq!("test", target0.name().unwrap());
714 assert_eq!(&Value::Int8Value(123), target0.value().unwrap());
715
716 let target = SqlParameter::of("test", Some(123_i64));
717 assert_eq!(target0, target);
718
719 let target = "test".parameter(123_i64);
720 assert_eq!(target0, target);
721
722 let target = "test".to_string().parameter(123_i64);
723 assert_eq!(target0, target);
724 }
725
726 #[test]
727 fn f32() {
728 let target0 = SqlParameter::of("test", 123_f32);
729 assert_eq!("test", target0.name().unwrap());
730 assert_eq!(&Value::Float4Value(123.0), target0.value().unwrap());
731
732 let target = SqlParameter::of("test", Some(123_f32));
733 assert_eq!(target0, target);
734
735 let target = "test".parameter(123_f32);
736 assert_eq!(target0, target);
737
738 let target = "test".to_string().parameter(123_f32);
739 assert_eq!(target0, target);
740 }
741
742 #[test]
743 fn f64() {
744 let target0 = SqlParameter::of("test", 123_f64);
745 assert_eq!("test", target0.name().unwrap());
746 assert_eq!(&Value::Float8Value(123.0), target0.value().unwrap());
747
748 let target = SqlParameter::of("test", Some(123_f64));
749 assert_eq!(target0, target);
750
751 let target = "test".parameter(123_f64);
752 assert_eq!(target0, target);
753
754 let target = "test".to_string().parameter(123_f64);
755 assert_eq!(target0, target);
756 }
757
758 #[test]
759 fn decimal() {
760 let value = TgDecimal::new(vec![4, 0xd2], -1);
761 let target0 = SqlParameter::of("test", value.clone());
762 assert_eq!("test", target0.name().unwrap());
763 assert_eq!(
764 &Value::DecimalValue(ProtoDecimal {
765 unscaled_value: vec![4, 0xd2],
766 exponent: -1
767 }),
768 target0.value().unwrap()
769 );
770
771 let target = SqlParameter::of("test", Some(value.clone()));
772 assert_eq!(target0, target);
773
774 let value = TgDecimalI128::new(1234, -1);
775 let target = SqlParameter::of("test", value.clone());
776 assert_eq!(target0.name(), target.name());
777 assert_eq!(
778 &Value::DecimalValue(ProtoDecimal {
779 unscaled_value: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0xd2],
780 exponent: -1
781 }),
782 target.value().unwrap()
783 );
784
785 let target1 = SqlParameter::of("test", Some(value.clone()));
786 assert_eq!(target1, target);
787 }
788
789 #[cfg(feature = "with_bigdecimal")]
790 #[test]
791 fn bigdecimal() {
792 use std::str::FromStr;
793
794 let value = bigdecimal::BigDecimal::from_str("123.4").unwrap();
795 let expected = value.as_bigint_and_exponent();
796
797 let target0 = SqlParameter::of("test", value.clone());
798 assert_eq!("test", target0.name().unwrap());
799 assert_eq!(
800 &Value::DecimalValue(ProtoDecimal {
801 unscaled_value: expected.0.to_signed_bytes_be(),
802 exponent: -expected.1 as i32
803 }),
804 target0.value().unwrap()
805 );
806
807 let target = SqlParameter::of("test", Some(value.clone()));
808 assert_eq!(target0, target);
809
810 let target = "test".parameter(value.clone());
811 assert_eq!(target0, target);
812
813 let target = "test".to_string().parameter(value.clone());
814 assert_eq!(target0, target);
815 }
816
817 #[cfg(feature = "with_bigdecimal")]
818 #[test]
819 fn bigdecimal_ref() {
820 use std::str::FromStr;
821
822 let value = bigdecimal::BigDecimal::from_str("123.4").unwrap();
823 let expected = value.as_bigint_and_exponent();
824
825 let target0 = SqlParameter::of("test", &value);
826 assert_eq!("test", target0.name().unwrap());
827 assert_eq!(
828 &Value::DecimalValue(ProtoDecimal {
829 unscaled_value: expected.0.to_signed_bytes_be(),
830 exponent: -expected.1 as i32
831 }),
832 target0.value().unwrap()
833 );
834
835 let target = SqlParameter::of("test", Some(&value));
836 assert_eq!(target0, target);
837
838 let target = "test".parameter(&value);
839 assert_eq!(target0, target);
840
841 let target = "test".to_string().parameter(&value);
842 assert_eq!(target0, target);
843 }
844
845 #[cfg(feature = "with_rust_decimal")]
846 #[test]
847 fn rust_decimal() {
848 use std::str::FromStr;
849
850 let value = rust_decimal::Decimal::from_str("123.4").unwrap();
851
852 let target0 = SqlParameter::of("test", value.clone());
853 assert_eq!("test", target0.name().unwrap());
854 assert_eq!(
855 &Value::DecimalValue(ProtoDecimal {
856 unscaled_value: value.mantissa().to_be_bytes().to_vec(),
857 exponent: -(value.scale() as i32)
858 }),
859 target0.value().unwrap()
860 );
861
862 let target = SqlParameter::of("test", Some(value.clone()));
863 assert_eq!(target0, target);
864
865 let target = "test".parameter(value.clone());
866 assert_eq!(target0, target);
867
868 let target = "test".to_string().parameter(value.clone());
869 assert_eq!(target0, target);
870 }
871
872 #[cfg(feature = "with_rust_decimal")]
873 #[test]
874 fn rust_decimal_ref() {
875 use std::str::FromStr;
876
877 let value = rust_decimal::Decimal::from_str("123.4").unwrap();
878
879 let target0 = SqlParameter::of("test", &value);
880 assert_eq!("test", target0.name().unwrap());
881 assert_eq!(
882 &Value::DecimalValue(ProtoDecimal {
883 unscaled_value: value.mantissa().to_be_bytes().to_vec(),
884 exponent: -(value.scale() as i32)
885 }),
886 target0.value().unwrap()
887 );
888
889 let target = SqlParameter::of("test", Some(&value));
890 assert_eq!(target0, target);
891
892 let target = "test".parameter(&value);
893 assert_eq!(target0, target);
894
895 let target = "test".to_string().parameter(&value);
896 assert_eq!(target0, target);
897 }
898
899 #[test]
900 fn str() {
901 let target0 = SqlParameter::of("test", "abc");
902 assert_eq!("test", target0.name().unwrap());
903 assert_eq!(
904 &Value::CharacterValue("abc".to_string()),
905 target0.value().unwrap()
906 );
907
908 let target = SqlParameter::of("test", Some("abc"));
909 assert_eq!(target0, target);
910
911 let target = "test".parameter("abc");
912 assert_eq!(target0, target);
913
914 let target = "test".to_string().parameter("abc");
915 assert_eq!(target0, target);
916 }
917
918 #[test]
919 fn string() {
920 let target0 = SqlParameter::of("test", "abc".to_string());
921 assert_eq!("test", target0.name().unwrap());
922 assert_eq!(
923 &Value::CharacterValue("abc".to_string()),
924 target0.value().unwrap()
925 );
926
927 let target = SqlParameter::of("test", Some("abc".to_string()));
928 assert_eq!(target0, target);
929
930 let target = "test".parameter("abc".to_string());
931 assert_eq!(target0, target);
932
933 let target = "test".to_string().parameter("abc".to_string());
934 assert_eq!(target0, target);
935 }
936
937 #[test]
938 fn string_ref() {
939 let target0 = SqlParameter::of("test", &"abc".to_string());
940 assert_eq!("test", target0.name().unwrap());
941 assert_eq!(
942 &Value::CharacterValue("abc".to_string()),
943 target0.value().unwrap()
944 );
945
946 let target = SqlParameter::of("test", Some(&"abc".to_string()));
947 assert_eq!(target0, target);
948
949 let target = "test".parameter(&"abc".to_string());
950 assert_eq!(target0, target);
951
952 let target = "test".to_string().parameter(&"abc".to_string());
953 assert_eq!(target0, target);
954 }
955
956 #[test]
957 fn array_u8() {
958 let value = [0x12_u8, 0x34, 0xef].as_slice();
959 let target0 = SqlParameter::of("test", value);
960 assert_eq!("test", target0.name().unwrap());
961 assert_eq!(&Value::OctetValue(value.to_vec()), target0.value().unwrap());
962
963 let target = SqlParameter::of("test", Some(value));
964 assert_eq!(target0, target);
965
966 let target = "test".parameter(value);
967 assert_eq!(target0, target);
968
969 let target = "test".to_string().parameter(value);
970 assert_eq!(target0, target);
971 }
972
973 #[test]
974 fn vec_u8() {
975 let value = vec![0x12_u8, 0x34, 0xef];
976 let target0 = SqlParameter::of("test", value.clone());
977 assert_eq!("test", target0.name().unwrap());
978 assert_eq!(&Value::OctetValue(value.clone()), target0.value().unwrap());
979
980 let target = SqlParameter::of("test", Some(value.clone()));
981 assert_eq!(target0, target);
982
983 let target = "test".parameter(value.clone());
984 assert_eq!(target0, target);
985
986 let target = "test".to_string().parameter(value.clone());
987 assert_eq!(target0, target);
988 }
989
990 #[test]
991 fn vec_u8_ref() {
992 let value = vec![0x12_u8, 0x34, 0xef];
993 let target0 = SqlParameter::of("test", &value);
994 assert_eq!("test", target0.name().unwrap());
995 assert_eq!(&Value::OctetValue(value.clone()), target0.value().unwrap());
996
997 let target = SqlParameter::of("test", Some(&value));
998 assert_eq!(target0, target);
999
1000 let target = "test".parameter(&value);
1001 assert_eq!(target0, target);
1002
1003 let target = "test".to_string().parameter(&value);
1004 assert_eq!(target0, target);
1005 }
1006
1007 #[test]
1008 fn date() {
1009 let value = TgDate::new(20126);
1010 let target0 = SqlParameter::of("test", value);
1011 assert_eq!("test", target0.name().unwrap());
1012 assert_eq!(
1013 &Value::DateValue(value.epoch_days),
1014 target0.value().unwrap()
1015 );
1016
1017 let target = SqlParameter::of("test", Some(value));
1018 assert_eq!(target0, target);
1019 }
1020
1021 #[test]
1022 fn time_of_day() {
1023 let value = TgTimeOfDay::new(30551971944200);
1024 let target0 = SqlParameter::of("test", value);
1025 assert_eq!("test", target0.name().unwrap());
1026 assert_eq!(
1027 &Value::TimeOfDayValue(value.offset_nanoseconds),
1028 target0.value().unwrap()
1029 );
1030
1031 let target = SqlParameter::of("test", Some(value));
1032 assert_eq!(target0, target);
1033 }
1034
1035 #[test]
1036 fn time_point() {
1037 let value = TgTimePoint::new(1738917213, 123456789);
1038 let target0 = SqlParameter::of("test", value.clone());
1039 assert_eq!("test", target0.name().unwrap());
1040 assert_eq!(
1041 &Value::TimePointValue(value.clone()),
1042 target0.value().unwrap()
1043 );
1044
1045 let target = SqlParameter::of("test", Some(value.clone()));
1046 assert_eq!(target0, target);
1047 }
1048
1049 #[test]
1050 fn time_of_day_with_time_zone() {
1051 let value = TgTimeOfDayWithTimeZone::new(30551971944200, 9 * 60);
1052 let target0 = SqlParameter::of("test", value.clone());
1053 assert_eq!("test", target0.name().unwrap());
1054 assert_eq!(
1055 &Value::TimeOfDayWithTimeZoneValue(value.clone()),
1056 target0.value().unwrap()
1057 );
1058
1059 let target = SqlParameter::of("test", Some(value.clone()));
1060 assert_eq!(target0, target);
1061 }
1062
1063 #[test]
1064 fn time_point_with_time_zone() {
1065 let value = TgTimePointWithTimeZone::new(1738917213, 123456789, 9 * 60);
1066 let target0 = SqlParameter::of("test", value.clone());
1067 assert_eq!("test", target0.name().unwrap());
1068 assert_eq!(
1069 &Value::TimePointWithTimeZoneValue(value.clone()),
1070 target0.value().unwrap()
1071 );
1072
1073 let target = SqlParameter::of("test", Some(value.clone()));
1074 assert_eq!(target0, target);
1075 }
1076
1077 #[cfg(feature = "with_chrono")]
1078 #[test]
1079 fn chrono_naive_date() {
1080 let value = chrono::NaiveDate::from_ymd_opt(2025, 1, 16).unwrap();
1081 let target0 = SqlParameter::of("test", value.clone());
1082 assert_eq!("test", target0.name().unwrap());
1083 assert_eq!(&Value::DateValue(20104), target0.value().unwrap());
1084
1085 let target = SqlParameter::of("test", Some(value.clone()));
1086 assert_eq!(target0, target);
1087
1088 let target = "test".parameter(value.clone());
1089 assert_eq!(target0, target);
1090
1091 let target = "test".to_string().parameter(value.clone());
1092 assert_eq!(target0, target);
1093 }
1094
1095 #[cfg(feature = "with_chrono")]
1096 #[test]
1097 fn chrono_naive_date_ref() {
1098 let value = chrono::NaiveDate::from_ymd_opt(2025, 1, 16).unwrap();
1099
1100 let target0 = SqlParameter::of("test", &value);
1101 assert_eq!("test", target0.name().unwrap());
1102 assert_eq!(&Value::DateValue(20104), target0.value().unwrap());
1103
1104 let target = SqlParameter::of("test", Some(&value));
1105 assert_eq!(target0, target);
1106
1107 let target = "test".parameter(&value);
1108 assert_eq!(target0, target);
1109
1110 let target = "test".to_string().parameter(&value);
1111 assert_eq!(target0, target);
1112 }
1113
1114 #[cfg(feature = "with_chrono")]
1115 #[test]
1116 fn chrono_naive_time() {
1117 let value = chrono::NaiveTime::from_hms_milli_opt(16, 24, 30, 456).unwrap();
1118 let target0 = SqlParameter::of("test", value.clone());
1119 assert_eq!("test", target0.name().unwrap());
1120 assert_eq!(
1121 &Value::TimeOfDayValue(59070456000000),
1122 target0.value().unwrap()
1123 );
1124
1125 let target = SqlParameter::of("test", Some(value.clone()));
1126 assert_eq!(target0, target);
1127
1128 let target = "test".parameter(value.clone());
1129 assert_eq!(target0, target);
1130
1131 let target = "test".to_string().parameter(value.clone());
1132 assert_eq!(target0, target);
1133 }
1134
1135 #[cfg(feature = "with_chrono")]
1136 #[test]
1137 fn chrono_naive_time_ref() {
1138 chrono_naive_time_ref_test(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap(), 0);
1139 chrono_naive_time_ref_test(
1140 chrono::NaiveTime::from_hms_opt(23, 59, 59).unwrap(),
1141 86399000000000,
1142 );
1143 chrono_naive_time_ref_test(
1144 chrono::NaiveTime::from_hms_nano_opt(0, 0, 0, 123456789).unwrap(),
1145 123456789,
1146 );
1147 chrono_naive_time_ref_test(
1148 chrono::NaiveTime::from_hms_nano_opt(23, 59, 59, 999999999).unwrap(),
1149 86399999999999,
1150 );
1151 }
1152
1153 #[cfg(feature = "with_chrono")]
1154 fn chrono_naive_time_ref_test(value: chrono::NaiveTime, expected: u64) {
1155 let target0 = SqlParameter::of("test", &value);
1156 assert_eq!("test", target0.name().unwrap());
1157 assert_eq!(&Value::TimeOfDayValue(expected), target0.value().unwrap());
1158
1159 let target = SqlParameter::of("test", Some(&value));
1160 assert_eq!(target0, target);
1161
1162 let target = "test".parameter(&value);
1163 assert_eq!(target0, target);
1164
1165 let target = "test".to_string().parameter(&value);
1166 assert_eq!(target0, target);
1167 }
1168
1169 #[cfg(feature = "with_chrono")]
1170 #[test]
1171 fn chrono_naive_date_time() {
1172 let value = chrono::NaiveDateTime::new(
1173 chrono::NaiveDate::from_ymd_opt(2025, 1, 16).unwrap(),
1174 chrono::NaiveTime::from_hms_nano_opt(17, 42, 30, 123456789).unwrap(),
1175 );
1176
1177 let target0 = SqlParameter::of("test", value.clone());
1178 assert_eq!("test", target0.name().unwrap());
1179 assert_eq!(
1180 &Value::TimePointValue(ProtoTimePoint {
1181 offset_seconds: 1737049350,
1182 nano_adjustment: 123456789
1183 }),
1184 target0.value().unwrap()
1185 );
1186
1187 let target = SqlParameter::of("test", Some(value.clone()));
1188 assert_eq!(target0, target);
1189
1190 let target = "test".parameter(value.clone());
1191 assert_eq!(target0, target);
1192
1193 let target = "test".to_string().parameter(value.clone());
1194 assert_eq!(target0, target);
1195 }
1196
1197 #[cfg(feature = "with_chrono")]
1198 #[test]
1199 fn chrono_naive_date_time_ref() {
1200 chrono_naive_date_time_ref_test(2025, 1, 16, 17, 42, 30, 123456789, 1737049350);
1201 chrono_naive_date_time_ref_test(1970, 1, 1, 0, 0, 0, 0, 0);
1202 chrono_naive_date_time_ref_test(1969, 12, 31, 23, 59, 59, 999999999, -1);
1203 }
1204
1205 #[cfg(feature = "with_chrono")]
1206 fn chrono_naive_date_time_ref_test(
1207 year: i32,
1208 month: u32,
1209 day: u32,
1210 hour: u32,
1211 min: u32,
1212 sec: u32,
1213 nanos: u32,
1214 expected_sec: i64,
1215 ) {
1216 let value = chrono::NaiveDateTime::new(
1217 chrono::NaiveDate::from_ymd_opt(year, month, day).unwrap(),
1218 chrono::NaiveTime::from_hms_nano_opt(hour, min, sec, nanos).unwrap(),
1219 );
1220
1221 let target0 = SqlParameter::of("test", &value);
1222 assert_eq!("test", target0.name().unwrap());
1223 assert_eq!(
1224 &Value::TimePointValue(ProtoTimePoint {
1225 offset_seconds: expected_sec,
1226 nano_adjustment: nanos
1227 }),
1228 target0.value().unwrap()
1229 );
1230
1231 let target = SqlParameter::of("test", Some(&value));
1232 assert_eq!(target0, target);
1233
1234 let target = "test".parameter(&value);
1235 assert_eq!(target0, target);
1236
1237 let target = "test".to_string().parameter(&value);
1238 assert_eq!(target0, target);
1239 }
1240
1241 #[cfg(feature = "with_chrono")]
1242 #[test]
1243 fn chrono_naive_time_with_offset() {
1244 use std::str::FromStr;
1245
1246 let time = chrono::NaiveTime::from_hms_nano_opt(17, 42, 30, 123456789).unwrap();
1247 let offset = chrono::FixedOffset::from_str("+09:00").unwrap();
1248 let value = (time, offset);
1249
1250 let target0 = SqlParameter::of("test", value.clone());
1251 assert_eq!("test", target0.name().unwrap());
1252 assert_eq!(
1253 &Value::TimeOfDayWithTimeZoneValue(ProtoTimeOfDayWithTimeZone {
1254 offset_nanoseconds: (((17 * 60) + 42) * 60 + 30) * 1_000_000_000 + 123456789,
1255 time_zone_offset: 9 * 60
1256 }),
1257 target0.value().unwrap()
1258 );
1259
1260 let target = SqlParameter::of("test", Some(value.clone()));
1261 assert_eq!(target0, target);
1262
1263 let target = "test".parameter(value.clone());
1264 assert_eq!(target0, target);
1265
1266 let target = "test".to_string().parameter(value.clone());
1267 assert_eq!(target0, target);
1268 }
1269
1270 #[cfg(feature = "with_chrono")]
1271 #[test]
1272 fn chrono_naive_time_with_offset_ref() {
1273 chrono_naive_time_with_offset_ref_test(17, 42, 30, 123456789, 9);
1274 chrono_naive_time_with_offset_ref_test(0, 0, 0, 0, 9);
1275 chrono_naive_time_with_offset_ref_test(23, 59, 59, 999999999, 9);
1276 chrono_naive_time_with_offset_ref_test(17, 42, 30, 123456789, -9);
1277 }
1278
1279 #[cfg(feature = "with_chrono")]
1280 fn chrono_naive_time_with_offset_ref_test(
1281 hour: u32,
1282 min: u32,
1283 sec: u32,
1284 nanos: u32,
1285 offset_hour: i32,
1286 ) {
1287 use std::str::FromStr;
1288
1289 let time = chrono::NaiveTime::from_hms_nano_opt(hour, min, sec, nanos).unwrap();
1290 let offset = if offset_hour >= 0 {
1291 format!("+{:02}:00", offset_hour)
1292 } else {
1293 format!("-{:02}:00", offset_hour.abs())
1294 };
1295 let offset = chrono::FixedOffset::from_str(&offset).unwrap();
1296 let value = (time, offset);
1297
1298 let target0 = SqlParameter::of("test", &value);
1299 assert_eq!("test", target0.name().unwrap());
1300 assert_eq!(
1301 &Value::TimeOfDayWithTimeZoneValue(ProtoTimeOfDayWithTimeZone {
1302 offset_nanoseconds: (((hour as u64 * 60) + min as u64) * 60 + sec as u64)
1303 * 1_000_000_000
1304 + nanos as u64,
1305 time_zone_offset: offset_hour * 60
1306 }),
1307 target0.value().unwrap()
1308 );
1309
1310 let target = SqlParameter::of("test", Some(&value));
1311 assert_eq!(target0, target);
1312
1313 let target = "test".parameter(&value);
1314 assert_eq!(target0, target);
1315
1316 let target = "test".to_string().parameter(&value);
1317 assert_eq!(target0, target);
1318 }
1319
1320 #[cfg(feature = "with_chrono")]
1321 #[test]
1322 fn chrono_date_time() {
1323 let value = date_time(2025, 1, 16, 17, 42, 30, 123456789, 9);
1324
1325 let target0 = SqlParameter::of("test", value.clone());
1326 assert_eq!("test", target0.name().unwrap());
1327 assert_eq!(
1328 &Value::TimePointWithTimeZoneValue(ProtoTimePointWithTimeZone {
1329 offset_seconds: 1737049350,
1330 nano_adjustment: 123456789,
1331 time_zone_offset: 9 * 60
1332 }),
1333 target0.value().unwrap()
1334 );
1335
1336 let target = SqlParameter::of("test", Some(value.clone()));
1337 assert_eq!(target0, target);
1338
1339 let target = "test".parameter(value.clone());
1340 assert_eq!(target0, target);
1341
1342 let target = "test".to_string().parameter(value.clone());
1343 assert_eq!(target0, target);
1344 }
1345
1346 #[cfg(feature = "with_chrono")]
1347 #[test]
1348 fn chrono_date_time_ref() {
1349 let value = date_time(2025, 1, 16, 17, 42, 30, 123456789, 9);
1350
1351 let target0 = SqlParameter::of("test", &value);
1352 assert_eq!("test", target0.name().unwrap());
1353 assert_eq!(
1354 &Value::TimePointWithTimeZoneValue(ProtoTimePointWithTimeZone {
1355 offset_seconds: 1737049350,
1356 nano_adjustment: 123456789,
1357 time_zone_offset: 9 * 60
1358 }),
1359 target0.value().unwrap()
1360 );
1361
1362 let target = SqlParameter::of("test", Some(&value));
1363 assert_eq!(target0, target);
1364
1365 let target = "test".parameter(&value);
1366 assert_eq!(target0, target);
1367
1368 let target = "test".to_string().parameter(&value);
1369 assert_eq!(target0, target);
1370 }
1371
1372 #[cfg(feature = "with_chrono")]
1373 fn date_time(
1374 year: i32,
1375 month: u32,
1376 day: u32,
1377 hour: u32,
1378 min: u32,
1379 sec: u32,
1380 nanos: u32,
1381 offset_hour: i32,
1382 ) -> chrono::DateTime<chrono::FixedOffset> {
1383 use std::str::FromStr;
1384
1385 let s = format!("{year:04}-{month:02}-{day:02} {hour:02}:{min:02}:{sec:02}.{nanos:09} +{offset_hour:02}:00");
1386 chrono::DateTime::from_str(&s).unwrap()
1387 }
1388
1389 #[cfg(feature = "with_time")]
1390 #[test]
1391 fn time_date() {
1392 let value = time::Date::from_calendar_date(2025, time::Month::January, 16).unwrap();
1393 let target0 = SqlParameter::of("test", value.clone());
1394 assert_eq!("test", target0.name().unwrap());
1395 assert_eq!(&Value::DateValue(20104), target0.value().unwrap());
1396
1397 let target = SqlParameter::of("test", Some(value.clone()));
1398 assert_eq!(target0, target);
1399
1400 let target = "test".parameter(value.clone());
1401 assert_eq!(target0, target);
1402
1403 let target = "test".to_string().parameter(value.clone());
1404 assert_eq!(target0, target);
1405 }
1406
1407 #[cfg(feature = "with_time")]
1408 #[test]
1409 fn time_date_ref() {
1410 time_date_ref_test(2025, 1, 16, 20104);
1411 time_date_ref_test(1970, 1, 1, 0);
1412 time_date_ref_test(1969, 12, 31, -1);
1413 time_date_ref_test(0, 1, 1, -719528);
1414 time_date_ref_test(9999, 12, 31, 2932896);
1415 time_date_ref_test(-9999, 1, 1, -4371587);
1416 }
1417
1418 #[cfg(feature = "with_time")]
1419 fn time_date_ref_test(year: i32, month: u8, day: u8, expected: i64) {
1420 let value =
1421 time::Date::from_calendar_date(year, time::Month::try_from(month).unwrap(), day)
1422 .unwrap();
1423 let target0 = SqlParameter::of("test", &value);
1424 assert_eq!("test", target0.name().unwrap());
1425 assert_eq!(&Value::DateValue(expected), target0.value().unwrap());
1426
1427 let target = SqlParameter::of("test", Some(&value));
1428 assert_eq!(target0, target);
1429
1430 let target = "test".parameter(&value);
1431 assert_eq!(target0, target);
1432
1433 let target = "test".to_string().parameter(&value);
1434 assert_eq!(target0, target);
1435 }
1436
1437 #[cfg(feature = "with_time")]
1438 #[test]
1439 fn time_time() {
1440 let value = time::Time::from_hms_milli(16, 24, 30, 456).unwrap();
1441 let target0 = SqlParameter::of("test", value.clone());
1442 assert_eq!("test", target0.name().unwrap());
1443 assert_eq!(
1444 &Value::TimeOfDayValue(59070456000000),
1445 target0.value().unwrap()
1446 );
1447
1448 let target = SqlParameter::of("test", Some(value.clone()));
1449 assert_eq!(target0, target);
1450
1451 let target = "test".parameter(value.clone());
1452 assert_eq!(target0, target);
1453
1454 let target = "test".to_string().parameter(value.clone());
1455 assert_eq!(target0, target);
1456 }
1457
1458 #[cfg(feature = "with_time")]
1459 #[test]
1460 fn time_time_ref() {
1461 time_time_ref_test(time::Time::from_hms(0, 0, 0).unwrap(), 0);
1462 time_time_ref_test(time::Time::from_hms(23, 59, 59).unwrap(), 86399000000000);
1463 time_time_ref_test(
1464 time::Time::from_hms_nano(0, 0, 0, 123456789).unwrap(),
1465 123456789,
1466 );
1467 time_time_ref_test(
1468 time::Time::from_hms_nano(23, 59, 59, 999999999).unwrap(),
1469 86399999999999,
1470 );
1471 }
1472
1473 #[cfg(feature = "with_time")]
1474 fn time_time_ref_test(value: time::Time, expected: u64) {
1475 let target0 = SqlParameter::of("test", &value);
1476 assert_eq!("test", target0.name().unwrap());
1477 assert_eq!(&Value::TimeOfDayValue(expected), target0.value().unwrap());
1478
1479 let target = SqlParameter::of("test", Some(&value));
1480 assert_eq!(target0, target);
1481
1482 let target = "test".parameter(&value);
1483 assert_eq!(target0, target);
1484
1485 let target = "test".to_string().parameter(&value);
1486 assert_eq!(target0, target);
1487 }
1488
1489 #[cfg(feature = "with_time")]
1490 #[test]
1491 fn time_primitive_date_time() {
1492 let value = time::PrimitiveDateTime::new(
1493 time::Date::from_calendar_date(2025, time::Month::January, 16).unwrap(),
1494 time::Time::from_hms_nano(17, 42, 30, 123456789).unwrap(),
1495 );
1496 let target0 = SqlParameter::of("test", value.clone());
1497 assert_eq!("test", target0.name().unwrap());
1498 assert_eq!(
1499 &Value::TimePointValue(ProtoTimePoint {
1500 offset_seconds: 1737049350,
1501 nano_adjustment: 123456789
1502 }),
1503 target0.value().unwrap()
1504 );
1505
1506 let target = SqlParameter::of("test", Some(value.clone()));
1507 assert_eq!(target0, target);
1508
1509 let target = "test".parameter(value.clone());
1510 assert_eq!(target0, target);
1511
1512 let target = "test".to_string().parameter(value.clone());
1513 assert_eq!(target0, target);
1514 }
1515
1516 #[cfg(feature = "with_time")]
1517 #[test]
1518 fn time_primitive_date_time_ref() {
1519 time_primitive_date_time_ref_test(2025, 1, 16, 17, 42, 30, 123456789, 1737049350);
1520 time_primitive_date_time_ref_test(1970, 1, 1, 0, 0, 0, 0, 0);
1521 time_primitive_date_time_ref_test(1969, 12, 31, 23, 59, 59, 999999999, -1);
1522 }
1523
1524 #[cfg(feature = "with_time")]
1525 fn time_primitive_date_time_ref_test(
1526 year: i32,
1527 month: u8,
1528 day: u8,
1529 hour: u8,
1530 min: u8,
1531 sec: u8,
1532 nanos: u32,
1533 expected: i64,
1534 ) {
1535 let value = time::PrimitiveDateTime::new(
1536 time::Date::from_calendar_date(year, time::Month::try_from(month).unwrap(), day)
1537 .unwrap(),
1538 time::Time::from_hms_nano(hour, min, sec, nanos).unwrap(),
1539 );
1540 let target0 = SqlParameter::of("test", &value);
1541 assert_eq!("test", target0.name().unwrap());
1542 assert_eq!(
1543 &Value::TimePointValue(ProtoTimePoint {
1544 offset_seconds: expected,
1545 nano_adjustment: nanos
1546 }),
1547 target0.value().unwrap()
1548 );
1549
1550 let target = SqlParameter::of("test", Some(&value));
1551 assert_eq!(target0, target);
1552
1553 let target = "test".parameter(&value);
1554 assert_eq!(target0, target);
1555
1556 let target = "test".to_string().parameter(&value);
1557 assert_eq!(target0, target);
1558 }
1559
1560 #[cfg(feature = "with_time")]
1561 #[test]
1562 fn time_time_with_offset() {
1563 let time = time::Time::from_hms_nano(17, 42, 30, 123456789).unwrap();
1564 let offset = time::UtcOffset::from_hms(9, 0, 0).unwrap();
1565 let value = (time, offset);
1566
1567 let target0 = SqlParameter::of("test", value.clone());
1568 assert_eq!("test", target0.name().unwrap());
1569 assert_eq!(
1570 &Value::TimeOfDayWithTimeZoneValue(ProtoTimeOfDayWithTimeZone {
1571 offset_nanoseconds: (((17 * 60) + 42) * 60 + 30) * 1_000_000_000 + 123456789,
1572 time_zone_offset: 9 * 60
1573 }),
1574 target0.value().unwrap()
1575 );
1576
1577 let target = SqlParameter::of("test", Some(value.clone()));
1578 assert_eq!(target0, target);
1579
1580 let target = "test".parameter(value.clone());
1581 assert_eq!(target0, target);
1582
1583 let target = "test".to_string().parameter(value.clone());
1584 assert_eq!(target0, target);
1585 }
1586
1587 #[cfg(feature = "with_time")]
1588 #[test]
1589 fn time_naive_time_with_offset_ref() {
1590 time_time_with_offset_ref_test(17, 42, 30, 123456789, 9);
1591 time_time_with_offset_ref_test(0, 0, 0, 0, 9);
1592 time_time_with_offset_ref_test(23, 59, 59, 999999999, 9);
1593 time_time_with_offset_ref_test(17, 42, 30, 123456789, -9);
1594 }
1595
1596 #[cfg(feature = "with_time")]
1597 fn time_time_with_offset_ref_test(hour: u8, min: u8, sec: u8, nanos: u32, offset_hour: i8) {
1598 let time = time::Time::from_hms_nano(hour, min, sec, nanos).unwrap();
1599 let offset = time::UtcOffset::from_hms(offset_hour, 0, 0).unwrap();
1600 let value = (time, offset);
1601
1602 let target0 = SqlParameter::of("test", &value);
1603 assert_eq!("test", target0.name().unwrap());
1604 assert_eq!(
1605 &Value::TimeOfDayWithTimeZoneValue(ProtoTimeOfDayWithTimeZone {
1606 offset_nanoseconds: (((hour as u64 * 60) + min as u64) * 60 + sec as u64)
1607 * 1_000_000_000
1608 + nanos as u64,
1609 time_zone_offset: offset_hour as i32 * 60
1610 }),
1611 target0.value().unwrap()
1612 );
1613
1614 let target = SqlParameter::of("test", Some(&value));
1615 assert_eq!(target0, target);
1616
1617 let target = "test".parameter(&value);
1618 assert_eq!(target0, target);
1619
1620 let target = "test".to_string().parameter(&value);
1621 assert_eq!(target0, target);
1622 }
1623
1624 #[cfg(feature = "with_time")]
1625 #[test]
1626 fn time_offset_date_time() {
1627 let value = offset_date_time(2025, 1, 16, 17, 42, 30, 123456789, 9);
1628
1629 let target0 = SqlParameter::of("test", value.clone());
1630 assert_eq!("test", target0.name().unwrap());
1631 assert_eq!(
1632 &Value::TimePointWithTimeZoneValue(ProtoTimePointWithTimeZone {
1633 offset_seconds: 1737049350,
1634 nano_adjustment: 123456789,
1635 time_zone_offset: 9 * 60
1636 }),
1637 target0.value().unwrap()
1638 );
1639
1640 let target = SqlParameter::of("test", Some(value.clone()));
1641 assert_eq!(target0, target);
1642
1643 let target = "test".parameter(value.clone());
1644 assert_eq!(target0, target);
1645
1646 let target = "test".to_string().parameter(value.clone());
1647 assert_eq!(target0, target);
1648 }
1649
1650 #[cfg(feature = "with_time")]
1651 #[test]
1652 fn time_offset_date_time_ref() {
1653 let value = offset_date_time(2025, 1, 16, 17, 42, 30, 123456789, 9);
1654
1655 let target0 = SqlParameter::of("test", &value);
1656 assert_eq!("test", target0.name().unwrap());
1657 assert_eq!(
1658 &Value::TimePointWithTimeZoneValue(ProtoTimePointWithTimeZone {
1659 offset_seconds: 1737049350,
1660 nano_adjustment: 123456789,
1661 time_zone_offset: 9 * 60
1662 }),
1663 target0.value().unwrap()
1664 );
1665
1666 let target = SqlParameter::of("test", Some(&value));
1667 assert_eq!(target0, target);
1668
1669 let target = "test".parameter(&value);
1670 assert_eq!(target0, target);
1671
1672 let target = "test".to_string().parameter(&value);
1673 assert_eq!(target0, target);
1674 }
1675
1676 #[cfg(feature = "with_time")]
1677 fn offset_date_time(
1678 year: i32,
1679 month: u8,
1680 day: u8,
1681 hour: u8,
1682 min: u8,
1683 sec: u8,
1684 nanos: u32,
1685 offset_hour: i32,
1686 ) -> time::OffsetDateTime {
1687 time::OffsetDateTime::new_in_offset(
1688 time::Date::from_calendar_date(year, time::Month::try_from(month).unwrap(), day)
1689 .unwrap(),
1690 time::Time::from_hms_nano(hour, min, sec, nanos).unwrap(),
1691 time::UtcOffset::from_whole_seconds(offset_hour * 60 * 60).unwrap(),
1692 )
1693 }
1694
1695 #[test]
1696 fn blob_path() {
1697 let value = TgBlob::new("/path/to/file");
1698 let target0 = SqlParameter::of("test", value.clone());
1699 assert_eq!("test", target0.name().unwrap());
1700 let data =
1701 crate::jogasaki::proto::sql::common::blob::Data::LocalPath("/path/to/file".to_string());
1702 assert_eq!(
1703 &Value::Blob(crate::jogasaki::proto::sql::common::Blob { data: Some(data) }),
1704 target0.value().unwrap()
1705 );
1706
1707 let target = SqlParameter::of("test", Some(value.clone()));
1708 assert_eq!(target0, target);
1709 }
1710
1711 #[test]
1712 fn blob_contents() {
1713 let contents = vec![1, 2, 3];
1714 let value = TgBlob::from(contents.clone());
1715 let target0 = SqlParameter::of("test", value.clone());
1716 assert_eq!("test", target0.name().unwrap());
1717 let data = crate::jogasaki::proto::sql::common::blob::Data::Contents(contents);
1718 assert_eq!(
1719 &Value::Blob(crate::jogasaki::proto::sql::common::Blob { data: Some(data) }),
1720 target0.value().unwrap()
1721 );
1722
1723 let target = SqlParameter::of("test", Some(value.clone()));
1724 assert_eq!(target0, target);
1725 }
1726
1727 #[test]
1728 fn clob_path() {
1729 let value = TgClob::new("/path/to/file");
1730 let target0 = SqlParameter::of("test", value.clone());
1731 assert_eq!("test", target0.name().unwrap());
1732 let data =
1733 crate::jogasaki::proto::sql::common::clob::Data::LocalPath("/path/to/file".to_string());
1734 assert_eq!(
1735 &Value::Clob(crate::jogasaki::proto::sql::common::Clob { data: Some(data) }),
1736 target0.value().unwrap()
1737 );
1738
1739 let target = SqlParameter::of("test", Some(value.clone()));
1740 assert_eq!(target0, target);
1741 }
1742
1743 #[test]
1744 fn clob_contents() {
1745 let contents = "abc";
1746 let value = TgClob::from(contents);
1747 let target0 = SqlParameter::of("test", value.clone());
1748 assert_eq!("test", target0.name().unwrap());
1749 let data =
1750 crate::jogasaki::proto::sql::common::clob::Data::Contents(contents.as_bytes().to_vec());
1751 assert_eq!(
1752 &Value::Clob(crate::jogasaki::proto::sql::common::Clob { data: Some(data) }),
1753 target0.value().unwrap()
1754 );
1755
1756 let target = SqlParameter::of("test", Some(value.clone()));
1757 assert_eq!(target0, target);
1758
1759 let value = TgClob::from(contents.to_string());
1760 let target = SqlParameter::of("test", value);
1761 assert_eq!(target0, target);
1762 }
1763}