|
1 | | -use etcd_client::{Client, ConnectOptions, TlsOptions, Identity, Certificate, Error, DeleteOptions, GetOptions, KeyValue, PutOptions}; |
| 1 | +use etcd_client::{Client, ConnectOptions, TlsOptions, Identity, Certificate, Error, DeleteOptions, GetOptions, KeyValue, PutOptions, SortTarget, SortOrder}; |
2 | 2 | use std::time::Duration; |
3 | 3 | use pgrx::pg_sys::panic::ErrorReport; |
4 | 4 | use pgrx::PgSqlErrorCode; |
@@ -86,6 +86,9 @@ pub enum EtcdFdwError { |
86 | 86 | #[error("Invalid option '{0}' with value '{1}'")] |
87 | 87 | InvalidOption(String, String), |
88 | 88 |
|
| 89 | + #[error("Invalid sort field value '{0}'")] |
| 90 | + InvalidSortField(String), |
| 91 | + |
89 | 92 | #[error("{0}")] |
90 | 93 | OptionsError(#[from] OptionsError), |
91 | 94 | } |
@@ -237,7 +240,7 @@ impl ForeignDataWrapper<EtcdFdwError> for EtcdFdw { |
237 | 240 | &mut self, |
238 | 241 | _quals: &[Qual], |
239 | 242 | columns: &[Column], |
240 | | - _sorts: &[Sort], |
| 243 | + sort: &[Sort], |
241 | 244 | limit: &Option<Limit>, |
242 | 245 | options: &std::collections::HashMap<String, String>, |
243 | 246 | ) -> Result<(), EtcdFdwError> { |
@@ -284,6 +287,30 @@ impl ForeignDataWrapper<EtcdFdwError> for EtcdFdw { |
284 | 287 | get_options = get_options.with_serializable(); |
285 | 288 | } |
286 | 289 |
|
| 290 | + // XXX Support for WHERE clause push-downs is pending |
| 291 | + // etcd doesn't have anything like WHERE clause because it |
| 292 | + // a NOSQL database. |
| 293 | + // But may be we can still support some simple WHERE |
| 294 | + // conditions like '<', '>=', 'LIKE', '=' by mapping them |
| 295 | + // to key, range_end and prefix options. |
| 296 | + |
| 297 | + // sort pushdown |
| 298 | + if let Some(first_sort) = sort.first() { |
| 299 | + let field_name = first_sort.field.to_ascii_uppercase(); |
| 300 | + |
| 301 | + if let Some(target) = SortTarget::from_str_name(&field_name) { |
| 302 | + let order = if first_sort.reversed { |
| 303 | + SortOrder::Descend |
| 304 | + } else { |
| 305 | + SortOrder::Ascend |
| 306 | + }; |
| 307 | + |
| 308 | + get_options = get_options.with_sort(target, order); |
| 309 | + } else { |
| 310 | + return Err(EtcdFdwError::InvalidSortField(first_sort.field.clone())); |
| 311 | + } |
| 312 | + } |
| 313 | + |
287 | 314 | // preference order : prefix > key_start > default "\0" |
288 | 315 | // samllest possible valid key '\0' |
289 | 316 | let key = prefix.clone() |
|
0 commit comments