pgx_sql_entity_graph/pg_extern/
operator.rs

1/*
2Portions Copyright 2019-2021 ZomboDB, LLC.
3Portions Copyright 2021-2022 Technology Concepts & Design, Inc. <support@tcdi.com>
4
5All rights reserved.
6
7Use of this source code is governed by the MIT license that can be found in the LICENSE file.
8*/
9/*!
10
11`#[pg_operator]` related macro expansion for Rust to SQL translation
12
13> Like all of the [`sql_entity_graph`][crate::pgx_sql_entity_graph] APIs, this is considered **internal**
14to the `pgx` framework and very subject to change between versions. While you may use this, please do it with caution.
15
16*/
17use proc_macro2::TokenStream as TokenStream2;
18use quote::{quote, ToTokens, TokenStreamExt};
19use syn::parenthesized;
20use syn::parse::{Parse, ParseBuffer};
21use syn::token::Paren;
22
23/// A parsed `#[pg_operator]` operator.
24///
25/// It is created during [`PgExtern`](crate::PgExtern) parsing.
26#[derive(Debug, Default, Clone)]
27pub struct PgOperator {
28    pub opname: Option<PgxOperatorOpName>,
29    pub commutator: Option<PgxOperatorAttributeWithIdent>,
30    pub negator: Option<PgxOperatorAttributeWithIdent>,
31    pub restrict: Option<PgxOperatorAttributeWithIdent>,
32    pub join: Option<PgxOperatorAttributeWithIdent>,
33    pub hashes: bool,
34    pub merges: bool,
35}
36
37impl ToTokens for PgOperator {
38    fn to_tokens(&self, tokens: &mut TokenStream2) {
39        let opname = self.opname.iter().clone();
40        let commutator = self.commutator.iter().clone();
41        let negator = self.negator.iter().clone();
42        let restrict = self.restrict.iter().clone();
43        let join = self.join.iter().clone();
44        let hashes = self.hashes;
45        let merges = self.merges;
46        let quoted = quote! {
47            ::pgx::pgx_sql_entity_graph::PgOperatorEntity {
48                opname: None #( .unwrap_or(Some(#opname)) )*,
49                commutator: None #( .unwrap_or(Some(#commutator)) )*,
50                negator: None #( .unwrap_or(Some(#negator)) )*,
51                restrict: None #( .unwrap_or(Some(#restrict)) )*,
52                join: None #( .unwrap_or(Some(#join)) )*,
53                hashes: #hashes,
54                merges: #merges,
55            }
56        };
57        tokens.append_all(quoted);
58    }
59}
60
61#[derive(Debug, Clone)]
62pub struct PgxOperatorAttributeWithIdent {
63    pub paren_token: Paren,
64    pub fn_name: TokenStream2,
65}
66
67impl Parse for PgxOperatorAttributeWithIdent {
68    fn parse(input: &ParseBuffer) -> Result<Self, syn::Error> {
69        let inner;
70        Ok(PgxOperatorAttributeWithIdent {
71            paren_token: parenthesized!(inner in input),
72            fn_name: inner.parse()?,
73        })
74    }
75}
76
77impl ToTokens for PgxOperatorAttributeWithIdent {
78    fn to_tokens(&self, tokens: &mut TokenStream2) {
79        let fn_name = &self.fn_name;
80        let operator = fn_name.to_string().replace(" ", "");
81        let quoted = quote! {
82            #operator
83        };
84        tokens.append_all(quoted);
85    }
86}
87
88#[derive(Debug, Clone)]
89pub struct PgxOperatorOpName {
90    pub paren_token: Paren,
91    pub op_name: TokenStream2,
92}
93
94impl Parse for PgxOperatorOpName {
95    fn parse(input: &ParseBuffer) -> Result<Self, syn::Error> {
96        let inner;
97        Ok(PgxOperatorOpName {
98            paren_token: parenthesized!(inner in input),
99            op_name: inner.parse()?,
100        })
101    }
102}
103
104impl ToTokens for PgxOperatorOpName {
105    fn to_tokens(&self, tokens: &mut TokenStream2) {
106        let op_name = &self.op_name;
107        let op_string = op_name.to_string().replacen(" ", "", 256);
108        let quoted = quote! {
109            #op_string
110        };
111        tokens.append_all(quoted);
112    }
113}