1use std::ops::ControlFlow;
16use std::time::Duration;
17
18use chrono::NaiveDate;
19use common_query::prelude::ScalarValue;
20use common_sql::convert::sql_value_to_value;
21use common_time::{Date, Timestamp};
22use datatypes::prelude::{ConcreteDataType, DataType};
23use datatypes::schema::ColumnSchema;
24use datatypes::types::TimestampType;
25use datatypes::value::{self, Value};
26#[cfg(test)]
27use itertools::Itertools;
28use opensrv_mysql::{ParamValue, ValueInner, to_naive_datetime};
29use snafu::ResultExt;
30use sql::ast::{Expr, Value as ValueExpr, ValueWithSpan, VisitMut, visit_expressions_mut};
31use sql::statements::statement::Statement;
32
33use crate::error::{self, Result};
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub(crate) struct PlaceholderSpan {
38 pub(crate) index: usize,
40 pub(crate) start_line: u64,
41 pub(crate) start_column: u64,
42 pub(crate) end_line: u64,
43 pub(crate) end_column: u64,
44}
45
46pub fn format_placeholder(i: usize) -> String {
48 format!("${}", i)
49}
50
51#[cfg(test)]
54pub fn replace_placeholders(query: &str) -> (String, usize) {
55 let query_parts = query.split('?').collect::<Vec<_>>();
56 let parts_len = query_parts.len();
57 let mut index = 0;
58 let query = query_parts
59 .into_iter()
60 .enumerate()
61 .map(|(i, part)| {
62 if i == parts_len - 1 {
63 return part.to_string();
64 }
65
66 index += 1;
67 format!("{part}{}", format_placeholder(index))
68 })
69 .join("");
70
71 (query, index + 1)
72}
73
74pub fn transform_placeholders_with_count(mut stmt: Statement) -> (Statement, usize) {
77 let count = visit_placeholders(&mut stmt);
78 (stmt, count)
79}
80
81pub(crate) fn placeholder_spans(mut stmt: Statement) -> Vec<PlaceholderSpan> {
83 let mut spans = Vec::new();
84 collect_placeholder_spans(&mut stmt, &mut spans);
85 spans
86}
87
88fn collect_placeholder_spans<V>(v: &mut V, spans: &mut Vec<PlaceholderSpan>)
89where
90 V: VisitMut,
91{
92 let _ = visit_expressions_mut(v, |expr| {
93 if let Expr::Value(ValueWithSpan {
94 value: ValueExpr::Placeholder(s),
95 span,
96 }) = expr
97 && let Some(index) = placeholder_index(s)
98 {
99 spans.push(PlaceholderSpan {
100 index,
101 start_line: span.start.line,
102 start_column: span.start.column,
103 end_line: span.end.line,
104 end_column: span.end.column,
105 });
106 }
107 ControlFlow::<()>::Continue(())
108 });
109}
110
111fn placeholder_index(s: &str) -> Option<usize> {
112 s.strip_prefix('$')?
113 .parse::<usize>()
114 .ok()
115 .filter(|i| *i > 0)
116}
117
118fn visit_placeholders<V>(v: &mut V) -> usize
119where
120 V: VisitMut,
121{
122 let mut index = 1;
123 let _ = visit_expressions_mut(v, |expr| {
124 if let Expr::Value(ValueWithSpan {
125 value: ValueExpr::Placeholder(s),
126 ..
127 }) = expr
128 && s == "?"
129 {
130 *s = format_placeholder(index);
131 index += 1;
132 }
133 ControlFlow::<()>::Continue(())
134 });
135 index - 1
136}
137
138pub fn convert_value(param: &ParamValue, t: &ConcreteDataType) -> Result<ScalarValue> {
141 if let ConcreteDataType::Dictionary(dictionary) = t {
142 return Ok(ScalarValue::Dictionary(
143 Box::new(dictionary.key_type().as_arrow_type()),
144 Box::new(convert_value(param, dictionary.value_type())?),
145 ));
146 }
147
148 match param.value.into_inner() {
149 ValueInner::Int(i) => match t {
150 ConcreteDataType::Int8(_) => Ok(ScalarValue::Int8(Some(i as i8))),
151 ConcreteDataType::Int16(_) => Ok(ScalarValue::Int16(Some(i as i16))),
152 ConcreteDataType::Int32(_) => Ok(ScalarValue::Int32(Some(i as i32))),
153 ConcreteDataType::Int64(_) => Ok(ScalarValue::Int64(Some(i))),
154 ConcreteDataType::UInt8(_) => Ok(ScalarValue::UInt8(Some(i as u8))),
155 ConcreteDataType::UInt16(_) => Ok(ScalarValue::UInt16(Some(i as u16))),
156 ConcreteDataType::UInt32(_) => Ok(ScalarValue::UInt32(Some(i as u32))),
157 ConcreteDataType::UInt64(_) => Ok(ScalarValue::UInt64(Some(i as u64))),
158 ConcreteDataType::Float32(_) => Ok(ScalarValue::Float32(Some(i as f32))),
159 ConcreteDataType::Float64(_) => Ok(ScalarValue::Float64(Some(i as f64))),
160 ConcreteDataType::Boolean(_) => Ok(ScalarValue::Boolean(Some(i != 0))),
161 ConcreteDataType::Timestamp(ts_type) => Value::Timestamp(ts_type.create_timestamp(i))
162 .try_to_scalar_value(t)
163 .context(error::ConvertScalarValueSnafu),
164
165 _ => error::PreparedStmtTypeMismatchSnafu {
166 expected: t,
167 actual: param.coltype,
168 }
169 .fail(),
170 },
171 ValueInner::UInt(u) => match t {
172 ConcreteDataType::Int8(_) => Ok(ScalarValue::Int8(Some(u as i8))),
173 ConcreteDataType::Int16(_) => Ok(ScalarValue::Int16(Some(u as i16))),
174 ConcreteDataType::Int32(_) => Ok(ScalarValue::Int32(Some(u as i32))),
175 ConcreteDataType::Int64(_) => Ok(ScalarValue::Int64(Some(u as i64))),
176 ConcreteDataType::UInt8(_) => Ok(ScalarValue::UInt8(Some(u as u8))),
177 ConcreteDataType::UInt16(_) => Ok(ScalarValue::UInt16(Some(u as u16))),
178 ConcreteDataType::UInt32(_) => Ok(ScalarValue::UInt32(Some(u as u32))),
179 ConcreteDataType::UInt64(_) => Ok(ScalarValue::UInt64(Some(u))),
180 ConcreteDataType::Float32(_) => Ok(ScalarValue::Float32(Some(u as f32))),
181 ConcreteDataType::Float64(_) => Ok(ScalarValue::Float64(Some(u as f64))),
182 ConcreteDataType::Boolean(_) => Ok(ScalarValue::Boolean(Some(u != 0))),
183 ConcreteDataType::Timestamp(ts_type) => {
184 Value::Timestamp(ts_type.create_timestamp(u as i64))
185 .try_to_scalar_value(t)
186 .context(error::ConvertScalarValueSnafu)
187 }
188
189 _ => error::PreparedStmtTypeMismatchSnafu {
190 expected: t,
191 actual: param.coltype,
192 }
193 .fail(),
194 },
195 ValueInner::Double(f) => match t {
196 ConcreteDataType::Int8(_) => Ok(ScalarValue::Int8(Some(f as i8))),
197 ConcreteDataType::Int16(_) => Ok(ScalarValue::Int16(Some(f as i16))),
198 ConcreteDataType::Int32(_) => Ok(ScalarValue::Int32(Some(f as i32))),
199 ConcreteDataType::Int64(_) => Ok(ScalarValue::Int64(Some(f as i64))),
200 ConcreteDataType::UInt8(_) => Ok(ScalarValue::UInt8(Some(f as u8))),
201 ConcreteDataType::UInt16(_) => Ok(ScalarValue::UInt16(Some(f as u16))),
202 ConcreteDataType::UInt32(_) => Ok(ScalarValue::UInt32(Some(f as u32))),
203 ConcreteDataType::UInt64(_) => Ok(ScalarValue::UInt64(Some(f as u64))),
204 ConcreteDataType::Float32(_) => Ok(ScalarValue::Float32(Some(f as f32))),
205 ConcreteDataType::Float64(_) => Ok(ScalarValue::Float64(Some(f))),
206
207 _ => error::PreparedStmtTypeMismatchSnafu {
208 expected: t,
209 actual: param.coltype,
210 }
211 .fail(),
212 },
213 ValueInner::NULL => value::to_null_scalar_value(t).context(error::ConvertScalarValueSnafu),
214 ValueInner::Bytes(b) => match t {
215 ConcreteDataType::String(t) => {
216 let s = String::from_utf8_lossy(b).to_string();
217 if t.is_large() {
218 Ok(ScalarValue::LargeUtf8(Some(s)))
219 } else {
220 Ok(ScalarValue::Utf8(Some(s)))
221 }
222 }
223 ConcreteDataType::Binary(_) => Ok(ScalarValue::Binary(Some(b.to_vec()))),
224 ConcreteDataType::Timestamp(ts_type) => convert_bytes_to_timestamp(b, ts_type),
225 ConcreteDataType::Date(_) => convert_bytes_to_date(b),
226 _ => error::PreparedStmtTypeMismatchSnafu {
227 expected: t,
228 actual: param.coltype,
229 }
230 .fail(),
231 },
232 ValueInner::Date(_) => {
233 let date: common_time::Date = NaiveDate::from(param.value).into();
234 Ok(ScalarValue::Date32(Some(date.val())))
235 }
236 ValueInner::Datetime(_) => {
237 let timestamp_millis = to_naive_datetime(param.value)
238 .map_err(|e| {
239 error::MysqlValueConversionSnafu {
240 err_msg: e.to_string(),
241 }
242 .build()
243 })?
244 .and_utc()
245 .timestamp_millis();
246
247 match t {
248 ConcreteDataType::Timestamp(_) => Ok(ScalarValue::TimestampMillisecond(
249 Some(timestamp_millis),
250 None,
251 )),
252 _ => error::PreparedStmtTypeMismatchSnafu {
253 expected: t,
254 actual: param.coltype,
255 }
256 .fail(),
257 }
258 }
259 ValueInner::Time(_) => Ok(ScalarValue::Time64Nanosecond(Some(
260 Duration::from(param.value).as_millis() as i64,
261 ))),
262 }
263}
264
265pub fn convert_expr_to_scalar_value(param: &Expr, t: &ConcreteDataType) -> Result<ScalarValue> {
268 if let ConcreteDataType::Dictionary(dictionary) = t {
269 return Ok(ScalarValue::Dictionary(
270 Box::new(dictionary.key_type().as_arrow_type()),
271 Box::new(convert_expr_to_scalar_value(
272 param,
273 dictionary.value_type(),
274 )?),
275 ));
276 }
277
278 let column_schema = ColumnSchema::new("", t.clone(), true);
279 match param {
280 Expr::Value(v) => {
281 let v = sql_value_to_value(&column_schema, &v.value, None, None, true);
282 match v {
283 Ok(v) => v
284 .try_to_scalar_value(t)
285 .context(error::ConvertScalarValueSnafu),
286 Err(e) => error::InvalidParameterSnafu {
287 reason: e.to_string(),
288 }
289 .fail(),
290 }
291 }
292 Expr::UnaryOp { op, expr } if let Expr::Value(v) = &**expr => {
293 let v = sql_value_to_value(&column_schema, &v.value, None, Some(*op), true);
294 match v {
295 Ok(v) => v
296 .try_to_scalar_value(t)
297 .context(error::ConvertScalarValueSnafu),
298 Err(e) => error::InvalidParameterSnafu {
299 reason: e.to_string(),
300 }
301 .fail(),
302 }
303 }
304 _ => error::InvalidParameterSnafu {
305 reason: format!("cannot convert {:?} to scalar value of type {}", param, t),
306 }
307 .fail(),
308 }
309}
310
311fn convert_bytes_to_timestamp(bytes: &[u8], ts_type: &TimestampType) -> Result<ScalarValue> {
312 let ts = Timestamp::from_str_utc(&String::from_utf8_lossy(bytes))
313 .map_err(|e| {
314 error::MysqlValueConversionSnafu {
315 err_msg: e.to_string(),
316 }
317 .build()
318 })?
319 .convert_to(ts_type.unit())
320 .ok_or_else(|| {
321 error::MysqlValueConversionSnafu {
322 err_msg: "Overflow when converting timestamp to target unit".to_string(),
323 }
324 .build()
325 })?;
326 match ts_type {
327 TimestampType::Nanosecond(_) => {
328 Ok(ScalarValue::TimestampNanosecond(Some(ts.value()), None))
329 }
330 TimestampType::Microsecond(_) => {
331 Ok(ScalarValue::TimestampMicrosecond(Some(ts.value()), None))
332 }
333 TimestampType::Millisecond(_) => {
334 Ok(ScalarValue::TimestampMillisecond(Some(ts.value()), None))
335 }
336 TimestampType::Second(_) => Ok(ScalarValue::TimestampSecond(Some(ts.value()), None)),
337 }
338}
339
340fn convert_bytes_to_date(bytes: &[u8]) -> Result<ScalarValue> {
341 let date = Date::from_str_utc(&String::from_utf8_lossy(bytes)).map_err(|e| {
342 error::MysqlValueConversionSnafu {
343 err_msg: e.to_string(),
344 }
345 .build()
346 })?;
347
348 Ok(ScalarValue::Date32(Some(date.val())))
349}
350
351#[cfg(test)]
352mod tests {
353 use datatypes::types::{
354 TimestampMicrosecondType, TimestampMillisecondType, TimestampNanosecondType,
355 TimestampSecondType,
356 };
357 use sql::dialect::MySqlDialect;
358 use sql::parser::{ParseOptions, ParserContext};
359
360 use super::*;
361
362 #[test]
363 fn test_format_placeholder() {
364 assert_eq!("$1", format_placeholder(1));
365 assert_eq!("$3", format_placeholder(3));
366 }
367
368 #[test]
369 fn test_replace_placeholders() {
370 let create = "create table demo(host string, ts timestamp time index)";
371 let (sql, index) = replace_placeholders(create);
372 assert_eq!(create, sql);
373 assert_eq!(1, index);
374
375 let insert = "insert into demo values(?,?,?)";
376 let (sql, index) = replace_placeholders(insert);
377 assert_eq!("insert into demo values($1,$2,$3)", sql);
378 assert_eq!(4, index);
379
380 let query = "select from demo where host=? and idc in (select idc from idcs where name=?) and cpu>?";
381 let (sql, index) = replace_placeholders(query);
382 assert_eq!(
383 "select from demo where host=$1 and idc in (select idc from idcs where name=$2) and cpu>$3",
384 sql
385 );
386 assert_eq!(4, index);
387 }
388
389 fn parse_sql(sql: &str) -> Statement {
390 let mut stmts =
391 ParserContext::create_with_dialect(sql, &MySqlDialect {}, ParseOptions::default())
392 .unwrap();
393 stmts.remove(0)
394 }
395
396 #[test]
397 fn test_transform_placeholders() {
398 let insert = parse_sql("insert into demo values(?,?,?)");
399 let (stmt, count) = transform_placeholders_with_count(insert);
400 let Statement::Insert(insert) = stmt else {
401 unreachable!()
402 };
403 assert_eq!(
404 "INSERT INTO demo VALUES ($1, $2, $3)",
405 insert.inner.to_string()
406 );
407 assert_eq!(3, count);
408
409 let delete = parse_sql("delete from demo where host=? and idc=?");
410 let (stmt, count) = transform_placeholders_with_count(delete);
411 let Statement::Delete(delete) = stmt else {
412 unreachable!()
413 };
414 assert_eq!(
415 "DELETE FROM demo WHERE host = $1 AND idc = $2",
416 delete.inner.to_string()
417 );
418 assert_eq!(2, count);
419
420 let select = parse_sql(
421 "select * from demo where host=? and idc in (select idc from idcs where name=?) and cpu>?",
422 );
423 let (stmt, count) = transform_placeholders_with_count(select);
424 let Statement::Query(select) = stmt else {
425 unreachable!()
426 };
427 assert_eq!(
428 "SELECT * FROM demo WHERE host = $1 AND idc IN (SELECT idc FROM idcs WHERE name = $2) AND cpu > $3",
429 select.inner.to_string()
430 );
431 assert_eq!(3, count);
432
433 let select = parse_sql("select '?', ?");
434 let (stmt, count) = transform_placeholders_with_count(select);
435 let Statement::Query(select) = stmt else {
436 unreachable!()
437 };
438 assert_eq!("SELECT '?', $1", select.inner.to_string());
439 assert_eq!(1, count);
440
441 let set = parse_sql("set time_zone = ?");
442 let (stmt, count) = transform_placeholders_with_count(set);
443 assert_eq!("SET time_zone = $1", stmt.to_string());
444 assert_eq!(1, count);
445 }
446
447 #[test]
448 fn test_convert_expr_to_scalar_value() {
449 let expr = Expr::Value(ValueExpr::Number("123".to_string(), false).into());
450 let t = ConcreteDataType::int32_datatype();
451 let v = convert_expr_to_scalar_value(&expr, &t).unwrap();
452 assert_eq!(ScalarValue::Int32(Some(123)), v);
453
454 let expr = Expr::Value(ValueExpr::Number("123.456789".to_string(), false).into());
455 let t = ConcreteDataType::float64_datatype();
456 let v = convert_expr_to_scalar_value(&expr, &t).unwrap();
457 assert_eq!(ScalarValue::Float64(Some(123.456789)), v);
458
459 let expr = Expr::Value(ValueExpr::SingleQuotedString("2001-01-02".to_string()).into());
460 let t = ConcreteDataType::date_datatype();
461 let v = convert_expr_to_scalar_value(&expr, &t).unwrap();
462 let scalar_v = ScalarValue::Utf8(Some("2001-01-02".to_string()))
463 .cast_to(&arrow_schema::DataType::Date32)
464 .unwrap();
465 assert_eq!(scalar_v, v);
466
467 let expr =
468 Expr::Value(ValueExpr::SingleQuotedString("2001-01-02 03:04:05".to_string()).into());
469 let t = ConcreteDataType::timestamp_microsecond_datatype();
470 let v = convert_expr_to_scalar_value(&expr, &t).unwrap();
471 let scalar_v = ScalarValue::Utf8(Some("2001-01-02 03:04:05".to_string()))
472 .cast_to(&arrow_schema::DataType::Timestamp(
473 arrow_schema::TimeUnit::Microsecond,
474 None,
475 ))
476 .unwrap();
477 assert_eq!(scalar_v, v);
478
479 let expr = Expr::Value(ValueExpr::SingleQuotedString("hello".to_string()).into());
480 let t = ConcreteDataType::string_datatype();
481 let v = convert_expr_to_scalar_value(&expr, &t).unwrap();
482 assert_eq!(ScalarValue::Utf8(Some("hello".to_string())), v);
483
484 let t = ConcreteDataType::dictionary_datatype(
485 ConcreteDataType::uint32_datatype(),
486 ConcreteDataType::string_datatype(),
487 );
488 let v = convert_expr_to_scalar_value(&expr, &t).unwrap();
489 assert_eq!(
490 ScalarValue::Dictionary(
491 Box::new(arrow_schema::DataType::UInt32),
492 Box::new(ScalarValue::Utf8(Some("hello".to_string()))),
493 ),
494 v
495 );
496
497 let expr = Expr::Value(ValueExpr::Null.into());
498 let t = ConcreteDataType::time_microsecond_datatype();
499 let v = convert_expr_to_scalar_value(&expr, &t).unwrap();
500 assert_eq!(ScalarValue::Time64Microsecond(None), v);
501 }
502
503 #[test]
504 fn test_convert_bytes_to_timestamp() {
505 let test_cases = vec![
506 (
508 "2024-12-26 12:00:00",
509 TimestampType::Nanosecond(TimestampNanosecondType),
510 ScalarValue::TimestampNanosecond(Some(1735214400000000000), None),
511 ),
512 (
514 "2024-12-26 12:00:00",
515 TimestampType::Microsecond(TimestampMicrosecondType),
516 ScalarValue::TimestampMicrosecond(Some(1735214400000000), None),
517 ),
518 (
520 "2024-12-26 12:00:00",
521 TimestampType::Millisecond(TimestampMillisecondType),
522 ScalarValue::TimestampMillisecond(Some(1735214400000), None),
523 ),
524 (
526 "2024-12-26 12:00:00",
527 TimestampType::Second(TimestampSecondType),
528 ScalarValue::TimestampSecond(Some(1735214400), None),
529 ),
530 (
532 "2024-12-26 12:00:00.123",
533 TimestampType::Nanosecond(TimestampNanosecondType),
534 ScalarValue::TimestampNanosecond(Some(1735214400123000000), None),
535 ),
536 (
538 "2024-12-26 12:00:00.123",
539 TimestampType::Microsecond(TimestampMicrosecondType),
540 ScalarValue::TimestampMicrosecond(Some(1735214400123000), None),
541 ),
542 (
544 "2024-12-26 12:00:00.123",
545 TimestampType::Millisecond(TimestampMillisecondType),
546 ScalarValue::TimestampMillisecond(Some(1735214400123), None),
547 ),
548 (
550 "2024-12-26 12:00:00.123",
551 TimestampType::Second(TimestampSecondType),
552 ScalarValue::TimestampSecond(Some(1735214400), None),
553 ),
554 (
556 "2024-12-26 12:00:00.123456",
557 TimestampType::Nanosecond(TimestampNanosecondType),
558 ScalarValue::TimestampNanosecond(Some(1735214400123456000), None),
559 ),
560 (
562 "2024-12-26 12:00:00.123456",
563 TimestampType::Microsecond(TimestampMicrosecondType),
564 ScalarValue::TimestampMicrosecond(Some(1735214400123456), None),
565 ),
566 (
568 "2024-12-26 12:00:00.123456",
569 TimestampType::Millisecond(TimestampMillisecondType),
570 ScalarValue::TimestampMillisecond(Some(1735214400123), None),
571 ),
572 (
574 "2024-12-26 12:00:00.123456",
575 TimestampType::Second(TimestampSecondType),
576 ScalarValue::TimestampSecond(Some(1735214400), None),
577 ),
578 ];
579
580 for (input, ts_type, expected) in test_cases {
581 let result = convert_bytes_to_timestamp(input.as_bytes(), &ts_type).unwrap();
582 assert_eq!(result, expected);
583 }
584 }
585
586 #[test]
587 fn test_convert_bytes_to_date() {
588 let test_cases = vec![
589 ("1970-01-01", ScalarValue::Date32(Some(0))),
591 ("1969-12-31", ScalarValue::Date32(Some(-1))),
592 ("2024-02-29", ScalarValue::Date32(Some(19782))),
593 ("2024-01-01", ScalarValue::Date32(Some(19723))),
594 ("2024-12-31", ScalarValue::Date32(Some(20088))),
595 ("2001-01-02", ScalarValue::Date32(Some(11324))),
596 ("2050-06-14", ScalarValue::Date32(Some(29384))),
597 ("2020-03-15", ScalarValue::Date32(Some(18336))),
598 ];
599
600 for (input, expected) in test_cases {
601 let result = convert_bytes_to_date(input.as_bytes()).unwrap();
602 assert_eq!(result, expected, "Failed for input: {}", input);
603 }
604 }
605}