| 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 |