1use crate::Expression;
2use crate::pg::Pg;
3use crate::query_builder::ColumnList;
4use crate::query_builder::QueryFragment;
5use crate::query_builder::nodes::StaticQueryFragment;
6use crate::sql_types::SqlType;
7use crate::{Column, Table};
8
9pub(crate) mod copy_from;
10pub(crate) mod copy_to;
11
12#[cfg(feature = "postgres")]
13pub(crate) use self::copy_from::{CopyFromExpression, InternalCopyFromQuery};
14#[cfg(feature = "postgres")]
15pub(crate) use self::copy_to::CopyToCommand;
16
17pub use self::copy_from::{CopyFromQuery, CopyHeader, ExecuteCopyFromDsl};
18pub use self::copy_to::CopyToQuery;
19
20const COPY_MAGIC_HEADER: [u8; 11] = [
21 0x50, 0x47, 0x43, 0x4F, 0x50, 0x59, 0x0A, 0xFF, 0x0D, 0x0A, 0x00,
22];
23
24#[derive(#[automatically_derived]
impl ::core::default::Default for CopyFormat {
#[inline]
fn default() -> CopyFormat { Self::Text }
}Default, #[automatically_derived]
impl ::core::fmt::Debug for CopyFormat {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
CopyFormat::Text => "Text",
CopyFormat::Csv => "Csv",
CopyFormat::Binary => "Binary",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for CopyFormat { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CopyFormat {
#[inline]
fn clone(&self) -> CopyFormat { *self }
}Clone)]
30pub enum CopyFormat {
31 #[default]
35 Text,
36 Csv,
38 Binary,
40}
41
42impl CopyFormat {
43 fn to_sql_format(self) -> &'static str {
44 match self {
45 CopyFormat::Text => "text",
46 CopyFormat::Csv => "csv",
47 CopyFormat::Binary => "binary",
48 }
49 }
50}
51
52#[derive(#[automatically_derived]
impl ::core::default::Default for CommonOptions {
#[inline]
fn default() -> CommonOptions {
CommonOptions {
format: ::core::default::Default::default(),
freeze: ::core::default::Default::default(),
delimiter: ::core::default::Default::default(),
null: ::core::default::Default::default(),
quote: ::core::default::Default::default(),
escape: ::core::default::Default::default(),
}
}
}Default, #[automatically_derived]
impl ::core::fmt::Debug for CommonOptions {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["format", "freeze", "delimiter", "null", "quote", "escape"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.format, &self.freeze, &self.delimiter, &self.null,
&self.quote, &&self.escape];
::core::fmt::Formatter::debug_struct_fields_finish(f, "CommonOptions",
names, values)
}
}Debug)]
53struct CommonOptions {
54 format: Option<CopyFormat>,
55 freeze: Option<bool>,
56 delimiter: Option<char>,
57 null: Option<String>,
58 quote: Option<char>,
59 escape: Option<char>,
60}
61
62impl CommonOptions {
63 fn any_set(&self) -> bool {
64 self.format.is_some()
65 || self.freeze.is_some()
66 || self.delimiter.is_some()
67 || self.null.is_some()
68 || self.quote.is_some()
69 || self.escape.is_some()
70 }
71
72 fn walk_ast<'b>(
73 &'b self,
74 mut pass: crate::query_builder::AstPass<'_, 'b, Pg>,
75 comma: &mut &'static str,
76 ) {
77 if let Some(format) = self.format {
78 pass.push_sql(comma);
79 *comma = ", ";
80 pass.push_sql("FORMAT ");
81 pass.push_sql(format.to_sql_format());
82 }
83 if let Some(freeze) = self.freeze {
84 pass.push_sql(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}FREEZE {0}", freeze as u8,
comma))
})format!("{comma}FREEZE {}", freeze as u8));
85 *comma = ", ";
86 }
87 if let Some(delimiter) = self.delimiter {
88 let delimiter = if delimiter == '\'' {
90 "''".into()
91 } else {
92 String::from(delimiter)
93 };
94 pass.push_sql(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}DELIMITER \'{1}\'", comma,
delimiter))
})format!("{comma}DELIMITER '{delimiter}'"));
95 *comma = ", ";
96 }
97 if let Some(ref null) = self.null {
98 pass.push_sql(comma);
99 *comma = ", ";
100 let null = null.replace('\'', "''");
104 pass.push_sql("NULL '");
105 pass.push_sql(&null);
106 pass.push_sql("'");
107 }
108 if let Some(quote) = self.quote {
109 let quote = if quote == '\'' {
111 "''".into()
112 } else {
113 String::from(quote)
114 };
115 pass.push_sql(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}QUOTE \'{1}\'", comma, quote))
})format!("{comma}QUOTE '{quote}'"));
116 *comma = ", ";
117 }
118 if let Some(escape) = self.escape {
119 let escape = if escape == '\'' {
121 "''".into()
122 } else {
123 String::from(escape)
124 };
125 pass.push_sql(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}ESCAPE \'{1}\'", comma, escape))
})format!("{comma}ESCAPE '{escape}'"));
126 *comma = ", ";
127 }
128 }
129}
130
131pub trait CopyTarget {
135 type Table: Table;
137 type SqlType: SqlType;
139
140 #[doc(hidden)]
141 fn walk_target(pass: crate::query_builder::AstPass<'_, '_, Pg>) -> crate::QueryResult<()>;
142}
143
144impl<T> CopyTarget for T
145where
146 T: Table + StaticQueryFragment,
147 T::SqlType: SqlType,
148 T::AllColumns: ColumnList,
149 T::Component: QueryFragment<Pg>,
150{
151 type Table = Self;
152 type SqlType = T::SqlType;
153
154 fn walk_target(mut pass: crate::query_builder::AstPass<'_, '_, Pg>) -> crate::QueryResult<()> {
155 T::STATIC_COMPONENT.walk_ast(pass.reborrow())?;
156 pass.push_sql("(");
157 T::all_columns().walk_ast(pass.reborrow())?;
158 pass.push_sql(")");
159 Ok(())
160 }
161}
162
163macro_rules! copy_target_for_columns {
164 ($(
165 $Tuple:tt {
166 $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
167 }
168 )+) => {
169 $(
170 impl<T, $($ST,)*> CopyTarget for ($($ST,)*)
171 where
172 $($ST: Column<Table = T> + Default,)*
173 ($(<$ST as Expression>::SqlType,)*): SqlType,
174 T: Table + StaticQueryFragment,
175 T::Component: QueryFragment<Pg>,
176 Self: ColumnList,
177 {
178 type Table = T;
179 type SqlType = crate::dsl::SqlTypeOf<Self>;
180
181 fn walk_target(
182 mut pass: crate::query_builder::AstPass<'_, '_, Pg>,
183 ) -> crate::QueryResult<()> {
184 T::STATIC_COMPONENT.walk_ast(pass.reborrow())?;
185 pass.push_sql("(");
186 <Self as ColumnList>::walk_ast(&($($ST::default(),)*), pass.reborrow())?;
187 pass.push_sql(")");
188 Ok(())
189 }
190 }
191 )*
192 }
193}
194
195impl<T, ST, ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8, ST9, ST10, ST11, ST12,
ST13, ST14, ST15, ST16, ST17, ST18, ST19, ST20, ST21, ST22, ST23, ST24,
ST25, ST26, ST27, ST28, ST29, ST30, ST31> CopyTarget for
(ST, ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8, ST9, ST10, ST11, ST12, ST13,
ST14, ST15, ST16, ST17, ST18, ST19, ST20, ST21, ST22, ST23, ST24, ST25,
ST26, ST27, ST28, ST29, ST30, ST31) where ST: Column<Table = T> + Default,
ST1: Column<Table = T> + Default, ST2: Column<Table = T> + Default,
ST3: Column<Table = T> + Default, ST4: Column<Table = T> + Default,
ST5: Column<Table = T> + Default, ST6: Column<Table = T> + Default,
ST7: Column<Table = T> + Default, ST8: Column<Table = T> + Default,
ST9: Column<Table = T> + Default, ST10: Column<Table = T> + Default,
ST11: Column<Table = T> + Default, ST12: Column<Table = T> + Default,
ST13: Column<Table = T> + Default, ST14: Column<Table = T> + Default,
ST15: Column<Table = T> + Default, ST16: Column<Table = T> + Default,
ST17: Column<Table = T> + Default, ST18: Column<Table = T> + Default,
ST19: Column<Table = T> + Default, ST20: Column<Table = T> + Default,
ST21: Column<Table = T> + Default, ST22: Column<Table = T> + Default,
ST23: Column<Table = T> + Default, ST24: Column<Table = T> + Default,
ST25: Column<Table = T> + Default, ST26: Column<Table = T> + Default,
ST27: Column<Table = T> + Default, ST28: Column<Table = T> + Default,
ST29: Column<Table = T> + Default, ST30: Column<Table = T> + Default,
ST31: Column<Table = T> + Default,
(<ST as Expression>::SqlType, <ST1 as Expression>::SqlType,
<ST2 as Expression>::SqlType, <ST3 as Expression>::SqlType,
<ST4 as Expression>::SqlType, <ST5 as Expression>::SqlType,
<ST6 as Expression>::SqlType, <ST7 as Expression>::SqlType,
<ST8 as Expression>::SqlType, <ST9 as Expression>::SqlType,
<ST10 as Expression>::SqlType, <ST11 as Expression>::SqlType,
<ST12 as Expression>::SqlType, <ST13 as Expression>::SqlType,
<ST14 as Expression>::SqlType, <ST15 as Expression>::SqlType,
<ST16 as Expression>::SqlType, <ST17 as Expression>::SqlType,
<ST18 as Expression>::SqlType, <ST19 as Expression>::SqlType,
<ST20 as Expression>::SqlType, <ST21 as Expression>::SqlType,
<ST22 as Expression>::SqlType, <ST23 as Expression>::SqlType,
<ST24 as Expression>::SqlType, <ST25 as Expression>::SqlType,
<ST26 as Expression>::SqlType, <ST27 as Expression>::SqlType,
<ST28 as Expression>::SqlType, <ST29 as Expression>::SqlType,
<ST30 as Expression>::SqlType, <ST31 as Expression>::SqlType): SqlType,
T: Table + StaticQueryFragment, T::Component: QueryFragment<Pg>,
Self: ColumnList {
type Table = T;
type SqlType = crate::dsl::SqlTypeOf<Self>;
fn walk_target(mut pass: crate::query_builder::AstPass<'_, '_, Pg>)
-> crate::QueryResult<()> {
T::STATIC_COMPONENT.walk_ast(pass.reborrow())?;
pass.push_sql("(");
<Self as
ColumnList>::walk_ast(&(ST::default(), ST1::default(),
ST2::default(), ST3::default(), ST4::default(),
ST5::default(), ST6::default(), ST7::default(),
ST8::default(), ST9::default(), ST10::default(),
ST11::default(), ST12::default(), ST13::default(),
ST14::default(), ST15::default(), ST16::default(),
ST17::default(), ST18::default(), ST19::default(),
ST20::default(), ST21::default(), ST22::default(),
ST23::default(), ST24::default(), ST25::default(),
ST26::default(), ST27::default(), ST28::default(),
ST29::default(), ST30::default(), ST31::default()),
pass.reborrow())?;
pass.push_sql(")");
Ok(())
}
}diesel_derives::__diesel_for_each_tuple!(copy_target_for_columns);