diesel/pg/query_builder/copy/
mod.rs1use crate::pg::Pg;
2use crate::query_builder::nodes::StaticQueryFragment;
3use crate::query_builder::ColumnList;
4use crate::query_builder::QueryFragment;
5use crate::sql_types::SqlType;
6use crate::Expression;
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)]
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 pass.push_sql(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}DELIMITER \'{1}\'", comma,
delimiter))
})format!("{comma}DELIMITER '{delimiter}'"));
89 *comma = ", ";
90 }
91 if let Some(ref null) = self.null {
92 pass.push_sql(comma);
93 *comma = ", ";
94 pass.push_sql("NULL '");
95 pass.push_sql(null);
97 pass.push_sql("'");
98 }
99 if let Some(quote) = self.quote {
100 pass.push_sql(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}QUOTE \'{1}\'", comma, quote))
})format!("{comma}QUOTE '{quote}'"));
101 *comma = ", ";
102 }
103 if let Some(escape) = self.escape {
104 pass.push_sql(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}ESCAPE \'{1}\'", comma, escape))
})format!("{comma}ESCAPE '{escape}'"));
105 *comma = ", ";
106 }
107 }
108}
109
110pub trait CopyTarget {
114 type Table: Table;
116 type SqlType: SqlType;
118
119 #[doc(hidden)]
120 fn walk_target(pass: crate::query_builder::AstPass<'_, '_, Pg>) -> crate::QueryResult<()>;
121}
122
123impl<T> CopyTarget for T
124where
125 T: Table + StaticQueryFragment,
126 T::SqlType: SqlType,
127 T::AllColumns: ColumnList,
128 T::Component: QueryFragment<Pg>,
129{
130 type Table = Self;
131 type SqlType = T::SqlType;
132
133 fn walk_target(mut pass: crate::query_builder::AstPass<'_, '_, Pg>) -> crate::QueryResult<()> {
134 T::STATIC_COMPONENT.walk_ast(pass.reborrow())?;
135 pass.push_sql("(");
136 T::all_columns().walk_ast(pass.reborrow())?;
137 pass.push_sql(")");
138 Ok(())
139 }
140}
141
142macro_rules! copy_target_for_columns {
143 ($(
144 $Tuple:tt {
145 $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
146 }
147 )+) => {
148 $(
149 impl<T, $($ST,)*> CopyTarget for ($($ST,)*)
150 where
151 $($ST: Column<Table = T> + Default,)*
152 ($(<$ST as Expression>::SqlType,)*): SqlType,
153 T: Table + StaticQueryFragment,
154 T::Component: QueryFragment<Pg>,
155 Self: ColumnList,
156 {
157 type Table = T;
158 type SqlType = crate::dsl::SqlTypeOf<Self>;
159
160 fn walk_target(
161 mut pass: crate::query_builder::AstPass<'_, '_, Pg>,
162 ) -> crate::QueryResult<()> {
163 T::STATIC_COMPONENT.walk_ast(pass.reborrow())?;
164 pass.push_sql("(");
165 <Self as ColumnList>::walk_ast(&($($ST::default(),)*), pass.reborrow())?;
166 pass.push_sql(")");
167 Ok(())
168 }
169 }
170 )*
171 }
172}
173
174impl<T, ST, ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8, ST9, ST10, ST11, ST12,
ST13, ST14, ST15> CopyTarget for
(ST, ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8, ST9, ST10, ST11, ST12, ST13,
ST14, ST15) 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,
(<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): 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()), pass.reborrow())?;
pass.push_sql(")");
Ok(())
}
}diesel_derives::__diesel_for_each_tuple!(copy_target_for_columns);