@@ -6,14 +6,14 @@ use crate::{
66 parser:: { QName , Template } ,
77} ;
88
9+ use anyhow:: { bail, Context , Error } ;
910use chrono_tz:: Tz ;
1011use data_encoding:: { DecodeError , DecodeKind , HEXLOWER_PERMISSIVE } ;
11- use failure:: { Error , Fail , ResultExt } ;
1212use flate2:: write:: GzEncoder ;
1313use muldiv:: MulDiv ;
1414use pbr:: { MultiBar , Units } ;
1515use rand:: {
16- rngs:: { EntropyRng , StdRng } ,
16+ rngs:: { OsRng , StdRng } ,
1717 Rng , RngCore , SeedableRng ,
1818} ;
1919use rayon:: {
@@ -22,8 +22,9 @@ use rayon::{
2222} ;
2323use serde_derive:: Deserialize ;
2424use std:: {
25+ error,
2526 fs:: { create_dir_all, read_to_string, File } ,
26- io:: { self , BufWriter , Write } ,
27+ io:: { self , stdin , BufWriter , Read , Write } ,
2728 path:: { Path , PathBuf } ,
2829 str:: FromStr ,
2930 sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ,
@@ -36,134 +37,78 @@ use xz2::write::XzEncoder;
3637/// Arguments to the `dbgen` CLI program.
3738#[ derive( StructOpt , Debug , Deserialize ) ]
3839#[ serde( default ) ]
39- #[ structopt( raw ( long_version = " ::FULL_VERSION" ) ) ]
40+ #[ structopt( long_version( crate :: FULL_VERSION ) ) ]
4041pub struct Args {
4142 /// Keep the qualified name when writing the SQL statements.
42- #[ structopt( long = "qualified" , help = "Keep the qualified name when writing the SQL statements" ) ]
43+ #[ structopt( long) ]
4344 pub qualified : bool ,
4445
4546 /// Override the table name.
46- #[ structopt( short = "t" , long = "table-name" , help = "Override the table name" ) ]
47+ #[ structopt( short, long) ]
4748 pub table_name : Option < String > ,
4849
4950 /// Output directory.
50- #[ structopt( short = "o" , long = "out-dir" , help = "Output directory" , parse( from_os_str) ) ]
51+ #[ structopt( short, long, parse( from_os_str) ) ]
5152 pub out_dir : PathBuf ,
5253
5354 /// Number of files to generate.
54- #[ structopt(
55- short = "k" ,
56- long = "files-count" ,
57- help = "Number of files to generate" ,
58- default_value = "1"
59- ) ]
55+ #[ structopt( short = "k" , long, default_value = "1" ) ]
6056 pub files_count : u32 ,
6157
6258 /// Number of INSERT statements per file.
63- #[ structopt(
64- short = "n" ,
65- long = "inserts-count" ,
66- help = "Number of INSERT statements per file" ,
67- default_value = "1"
68- ) ]
59+ #[ structopt( short = "n" , long, default_value = "1" ) ]
6960 pub inserts_count : u32 ,
7061
7162 /// Number of rows per INSERT statement.
72- #[ structopt(
73- short = "r" ,
74- long = "rows-count" ,
75- help = "Number of rows per INSERT statement" ,
76- default_value = "1"
77- ) ]
63+ #[ structopt( short, long, default_value = "1" ) ]
7864 pub rows_count : u32 ,
7965
8066 /// Number of INSERT statements in the last file.
81- #[ structopt(
82- long = "last-file-inserts-count" ,
83- help = "Number of INSERT statements in the last file"
84- ) ]
67+ #[ structopt( long) ]
8568 pub last_file_inserts_count : Option < u32 > ,
8669
8770 /// Number of rows of the last INSERT statement of the last file.
88- #[ structopt(
89- long = "last-insert-rows-count" ,
90- help = "Number of rows of the last INSERT statement of the last file"
91- ) ]
71+ #[ structopt( long) ]
9272 pub last_insert_rows_count : Option < u32 > ,
9373
94- /// Do not escape backslashes when writing a string.
95- #[ structopt( long = "escape-backslash" , help = "Escape backslashes when writing a string" ) ]
74+ /// Ecape backslashes when writing a string.
75+ #[ structopt( long) ]
9676 pub escape_backslash : bool ,
9777
9878 /// Generation template file.
99- #[ structopt(
100- short = "i" ,
101- long = "template" ,
102- help = "Generation template file" ,
103- parse( from_os_str)
104- ) ]
79+ #[ structopt( short = "i" , long, parse( from_os_str) ) ]
10580 pub template : PathBuf ,
10681
107- /// Random number generator seed.
108- #[ structopt(
109- short = "s" ,
110- long = "seed" ,
111- help = "Random number generator seed (should have 64 hex digits)" ,
112- parse( try_from_str = "seed_from_str" )
113- ) ]
82+ /// Random number generator seed (should have 64 hex digits).
83+ #[ structopt( short, long, parse( try_from_str = seed_from_str) ) ]
11484 pub seed : Option < <StdRng as SeedableRng >:: Seed > ,
11585
11686 /// Number of jobs to run in parallel, default to number of CPUs.
117- #[ structopt(
118- short = "j" ,
119- long = "jobs" ,
120- help = "Number of jobs to run in parallel, default to number of CPUs" ,
121- default_value = "0"
122- ) ]
87+ #[ structopt( short, long, default_value = "0" ) ]
12388 pub jobs : usize ,
12489
12590 /// Random number generator engine
126- #[ structopt(
127- long = "rng" ,
128- help = "Random number generator engine" ,
129- raw( possible_values = r#"&["chacha", "hc128", "isaac", "isaac64", "xorshift", "pcg32"]"# ) ,
130- default_value = "hc128"
131- ) ]
91+ #[ structopt( long, possible_values( & [ "chacha" , "hc128" , "isaac" , "isaac64" , "xorshift" , "pcg32" ] ) , default_value = "hc128" ) ]
13292 pub rng : RngName ,
13393
13494 /// Disable progress bar.
135- #[ structopt( short = "q" , long = "quiet" , help = "Disable progress bar" ) ]
95+ #[ structopt( short, long) ]
13696 pub quiet : bool ,
13797
138- /// Timezone
139- #[ structopt( long = "time-zone" , help = "Time zone used for timestamps" , default_value = "UTC" ) ]
98+ /// Time zone used for timestamps
99+ #[ structopt( long, default_value = "UTC" ) ]
140100 pub time_zone : Tz ,
141101
142102 /// Output format
143- #[ structopt(
144- short = "f" ,
145- long = "format" ,
146- help = "Output format" ,
147- raw( possible_values = r#"&["sql", "csv"]"# ) ,
148- default_value = "sql"
149- ) ]
103+ #[ structopt( short, long, possible_values( & [ "sql" , "csv" ] ) , default_value = "sql" ) ]
150104 pub format : FormatName ,
151105
152- /// Output compression
153- #[ structopt(
154- short = "c" ,
155- long = "compress" ,
156- help = "Compress data output" ,
157- raw( possible_values = r#"&["gzip", "gz", "xz", "zstd", "zst"]"# )
158- ) ]
106+ /// Compress data output
107+ #[ structopt( short, long, possible_values( & [ "gzip" , "gz" , "xz" , "zstd" , "zst" ] ) ) ]
159108 pub compression : Option < CompressionName > ,
160109
161- /// Output compression level
162- #[ structopt(
163- long = "compress-level" ,
164- help = "Compression level (0-9 for gzip and xz, 1-21 for zstd)" ,
165- default_value = "6"
166- ) ]
110+ /// Compression level (0-9 for gzip and xz, 1-21 for zstd)
111+ #[ structopt( long, default_value = "6" ) ]
167112 pub compress_level : u8 ,
168113}
169114
@@ -215,10 +160,10 @@ trait PathResultExt {
215160 fn with_path ( self , path : & Path ) -> Result < Self :: Ok , Error > ;
216161}
217162
218- impl < T , E : Fail > PathResultExt for Result < T , E > {
163+ impl < T , E : error :: Error + Send + Sync + ' static > PathResultExt for Result < T , E > {
219164 type Ok = T ;
220165 fn with_path ( self , path : & Path ) -> Result < T , Error > {
221- Ok ( self . with_context ( |_ | format ! ( "with file {}..." , path. display( ) ) ) ? )
166+ self . with_context ( || format ! ( "with file {}..." , path. display( ) ) )
222167 }
223168}
224169
@@ -231,7 +176,13 @@ static WRITTEN_SIZE: AtomicUsize = AtomicUsize::new(0);
231176
232177/// Runs the CLI program.
233178pub fn run ( args : Args ) -> Result < ( ) , Error > {
234- let input = read_to_string ( & args. template ) . context ( "failed to read template" ) ?;
179+ let input = if args. template != Path :: new ( "-" ) {
180+ read_to_string ( & args. template )
181+ } else {
182+ let mut buf = String :: new ( ) ;
183+ stdin ( ) . read_to_string ( & mut buf) . map ( move |_| buf)
184+ }
185+ . context ( "failed to read template" ) ?;
235186 let template = Template :: parse ( & input) ?;
236187
237188 let pool = ThreadPoolBuilder :: new ( )
@@ -269,7 +220,7 @@ pub fn run(args: Args) -> Result<(), Error> {
269220
270221 env. write_schema ( & template. content ) ?;
271222
272- let meta_seed = args. seed . unwrap_or_else ( || EntropyRng :: new ( ) . gen ( ) ) ;
223+ let meta_seed = args. seed . unwrap_or_else ( || OsRng . gen ( ) ) ;
273224 let show_progress = !args. quiet ;
274225 if show_progress {
275226 println ! ( "Using seed: {}" , HEXLOWER_PERMISSIVE . encode( & meta_seed) ) ;
@@ -358,7 +309,7 @@ impl FromStr for RngName {
358309 "isaac64" => RngName :: Isaac64 ,
359310 "xorshift" => RngName :: XorShift ,
360311 "pcg32" => RngName :: Pcg32 ,
361- _ => failure :: bail!( "Unsupported RNG {}" , name) ,
312+ _ => bail ! ( "Unsupported RNG {}" , name) ,
362313 } )
363314 }
364315}
@@ -392,7 +343,7 @@ impl FromStr for FormatName {
392343 Ok ( match name {
393344 "sql" => FormatName :: Sql ,
394345 "csv" => FormatName :: Csv ,
395- _ => failure :: bail!( "Unsupported format {}" , name) ,
346+ _ => bail ! ( "Unsupported output format {}" , name) ,
396347 } )
397348 }
398349}
@@ -433,7 +384,7 @@ impl FromStr for CompressionName {
433384 "gzip" | "gz" => CompressionName :: Gzip ,
434385 "xz" => CompressionName :: Xz ,
435386 "zstd" | "zst" => CompressionName :: Zstd ,
436- _ => failure :: bail!( "Unsupported format {}" , name) ,
387+ _ => bail ! ( "Unsupported compression format {}" , name) ,
437388 } )
438389 }
439390}
0 commit comments