1 | #include "duckdb/parser/transformer.hpp" |
---|---|
2 | #include "duckdb/parser/parsed_data/sample_options.hpp" |
3 | #include "duckdb/parser/expression/constant_expression.hpp" |
4 | #include "duckdb/common/string_util.hpp" |
5 | |
6 | namespace duckdb { |
7 | |
8 | static SampleMethod GetSampleMethod(const string &method) { |
9 | auto lmethod = StringUtil::Lower(str: method); |
10 | if (lmethod == "system") { |
11 | return SampleMethod::SYSTEM_SAMPLE; |
12 | } else if (lmethod == "bernoulli") { |
13 | return SampleMethod::BERNOULLI_SAMPLE; |
14 | } else if (lmethod == "reservoir") { |
15 | return SampleMethod::RESERVOIR_SAMPLE; |
16 | } else { |
17 | throw ParserException("Unrecognized sampling method %s, expected system, bernoulli or reservoir", method); |
18 | } |
19 | } |
20 | |
21 | unique_ptr<SampleOptions> Transformer::TransformSampleOptions(optional_ptr<duckdb_libpgquery::PGNode> options) { |
22 | if (!options) { |
23 | return nullptr; |
24 | } |
25 | auto result = make_uniq<SampleOptions>(); |
26 | auto &sample_options = PGCast<duckdb_libpgquery::PGSampleOptions>(node&: *options); |
27 | auto &sample_size = *PGPointerCast<duckdb_libpgquery::PGSampleSize>(ptr: sample_options.sample_size); |
28 | auto sample_value = TransformValue(val: sample_size.sample_size)->value; |
29 | result->is_percentage = sample_size.is_percentage; |
30 | if (sample_size.is_percentage) { |
31 | // sample size is given in sample_size: use system sampling |
32 | auto percentage = sample_value.GetValue<double>(); |
33 | if (percentage < 0 || percentage > 100) { |
34 | throw ParserException("Sample sample_size %llf out of range, must be between 0 and 100", percentage); |
35 | } |
36 | result->sample_size = Value::DOUBLE(value: percentage); |
37 | result->method = SampleMethod::SYSTEM_SAMPLE; |
38 | } else { |
39 | // sample size is given in rows: use reservoir sampling |
40 | auto rows = sample_value.GetValue<int64_t>(); |
41 | if (rows < 0) { |
42 | throw ParserException("Sample rows %lld out of range, must be bigger than or equal to 0", rows); |
43 | } |
44 | result->sample_size = Value::BIGINT(value: rows); |
45 | result->method = SampleMethod::RESERVOIR_SAMPLE; |
46 | } |
47 | if (sample_options.method) { |
48 | result->method = GetSampleMethod(method: sample_options.method); |
49 | } |
50 | if (sample_options.has_seed) { |
51 | result->seed = sample_options.seed; |
52 | } |
53 | return result; |
54 | } |
55 | |
56 | } // namespace duckdb |
57 |