<commit_before>use nom::multispace;
use nom::{Err, ErrorKind, IResult, Needed};
use std::str;

use select::{limit_clause, nested_selection, order_clause, LimitClause, OrderClause,
             SelectStatement};

#[derive(Clone, Debug, Hash, PartialEq, Deserialize, Serialize)]
pub enum CompoundOperation {
    Union,
    DistinctUnion,
    Intersect,
    Except,
}

#[derive(Clone, Debug, Hash, PartialEq, Deserialize, Serialize)]
pub struct CompoundSelectStatement {
    pub selects: Vec<(Option<CompoundOperation>, SelectStatement)>,
    pub order: Option<OrderClause>,
    pub limit: Option<LimitClause>,
}

/// Parse compound operator
named!(compound_op<&[u8], CompoundOperation>,
    alt_complete!(
          chain!(
              caseless_tag!("union") ~
              distinct: opt!(
                  preceded!(multispace,
                            alt_complete!(  map!(caseless_tag!("all"), |_| { false })
                                          | map!(caseless_tag!("distinct"), |_| { true }))
                            )),
              || {
                  match distinct {
                      // DISTINCT is the default in both MySQL and SQLite
                      None => CompoundOperation::DistinctUnion,
                      Some(d) => {
                          if d {
                              CompoundOperation::DistinctUnion
                          } else {
                              CompoundOperation::Union
                          }
                      },
                  }
              }
          )
        | map!(caseless_tag!("intersect"), |_| CompoundOperation::Intersect)
        | map!(caseless_tag!("except"), |_| CompoundOperation::Except)
    )
);

/// Parse compound selection
named!(pub compound_selection<&[u8], CompoundSelectStatement>,
    complete!(chain!(
        first_select: nested_selection ~
        other_selects: many0!(
            complete!(
                chain!(multispace? ~
                       op: compound_op ~
                       multispace ~
                       select: nested_selection ~
                       || {
                           (Some(op), select)
                       }<commit_msg>Avoid subsuming simple into compound selections<commit_after>use nom::multispace;
use nom::{Err, ErrorKind, IResult, Needed};
use std::str;

use select::{limit_clause, nested_selection, order_clause, LimitClause, OrderClause,
             SelectStatement};

#[derive(Clone, Debug, Hash, PartialEq, Deserialize, Serialize)]
pub enum CompoundOperation {
    Union,
    DistinctUnion,
    Intersect,
    Except,
}

#[derive(Clone, Debug, Hash, PartialEq, Deserialize, Serialize)]
pub struct CompoundSelectStatement {
    pub selects: Vec<(Option<CompoundOperation>, SelectStatement)>,
    pub order: Option<OrderClause>,
    pub limit: Option<LimitClause>,
}

/// Parse compound operator
named!(compound_op<&[u8], CompoundOperation>,
    alt_complete!(
          chain!(
              caseless_tag!("union") ~
              distinct: opt!(
                  preceded!(multispace,
                            alt_complete!(  map!(caseless_tag!("all"), |_| { false })
                                          | map!(caseless_tag!("distinct"), |_| { true }))
                            )),
              || {
                  match distinct {
                      // DISTINCT is the default in both MySQL and SQLite
                      None => CompoundOperation::DistinctUnion,
                      Some(d) => {
                          if d {
                              CompoundOperation::DistinctUnion
                          } else {
                              CompoundOperation::Union
                          }
                      },
                  }
              }
          )
        | map!(caseless_tag!("intersect"), |_| CompoundOperation::Intersect)
        | map!(caseless_tag!("except"), |_| CompoundOperation::Except)
    )
);

/// Parse compound selection
named!(pub compound_selection<&[u8], CompoundSelectStatement>,
    complete!(chain!(
        first_select: nested_selection ~
        other_selects: many1!(
            complete!(
                chain!(multispace? ~
                       op: compound_op ~
                       multispace ~
                       select: nested_selection ~
                       || {
                           (Some(op), select)
                       }
{'fraction_non_alphanumeric': 0.1057866184448463, 'fraction_numerical': 0.00135623869801085, 'mean_word_length': 1.5256849315068493, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '318475', 'n_tokens_mistral': 1102, 'n_tokens_neox': 1083, 'n_words': 219}