<commit_before>-----------------------------------------------------------------------------
-- |
-- Module      :  Database.TxtSushi.SQLFunctionDefinitions
-- Copyright   :  (c) <NAME> 2009
-- License     :  GPL3 or greater
-- Maintainer  :  <EMAIL>
-- Stability   :  experimental
-- Portability :  portable
--
-- SQL Functions
--
-----------------------------------------------------------------------------

module Database.TxtSushi.SQLFunctionDefinitions (
    SQLFunction(..),
    normalSyntaxFunctions,
    infixFunctions,
    specialFunctions,
    
    -- TODO remove these
    negateFunction,
    countFunction,
    substringFromToFunction,
    substringFromFunction,
    notFunction) where

import Data.Char
import Data.List
import Text.Regex.Posix

import Database.TxtSushi.EvaluatedExpression
import Database.TxtSushi.SQLExpression

-- Functions with "normal" syntax --
normalSyntaxFunctions :: [SQLFunction]
normalSyntaxFunctions =
    [absFunction, upperFunction, lowerFunction, trimFunction,
     -- all aggregates except count which accepts a (*)
     avgFunction, firstFunction, lastFunction, maxFunction,
     minFunction, sumFunction]

-- non aggregates
absFunction :: SQLFunction
absFunction = SQLFunction {
    functionName    = "ABS",
    minArgCount     = 1,
    argCountIsFixed = True,
    applyFunction   = applyUnaryNumeric absFunction abs abs}

upperFunction :: SQLFunction
upperFunction = SQLFunction {
    functionName    = "UPPER",
    minArgCount     = 1,
    argCountIsFixed = True,
    applyFunction   = applyUnaryString upperFunction (map toUpper)}

lowerFunction :: SQLFunction
lowerFunction = SQLFunction {
    functionName    = "LOWER",
    minArgCount     = 1,
    argCountIsFixed = True,
    applyFunction   = applyUnaryString lowerFunction (map toLower)}

trimFunction :: SQLFunction
trimFunction = SQLFunction {
    functionName    = "TRIM",
    minArgCount     = 1,
    argCountIsFixed = True,
    applyFunction   = applyUnaryString trimFunction trimSpace}

-- aggregates
avgFunction :: SQLFunction
avgFunction = SQLFunction {
    functionName    = "AVG",
    minArgCount     = 1,
    argCountIsFixed = False,
    applyFunction   = avgFun . checkArgCount avgFunction}
    -- TODO this AVG(...) holds the whole arg list in memory. reimplement!
    where
        avgFun args = RealExpression $
            foldl1' (+) (map coerceReal args) /
            (fromIntegral $ length args)

countFunction :: SQLFunction
countFunction = SQLFunction {
    functionName    = "COUNT",
    minArgCount     = 0,
    argCountIsFixed = False,
    applyFunction   = IntExpression . length}

firstFunction :: SQLFunction
firstFunction = SQLFunction {
    functionName    = "FIRST",
    minArgCount     = 1,
    argCountIsFixed = False,<commit_msg>added an IF_THEN_ELSE SQL function<commit_after>-----------------------------------------------------------------------------
-- |
-- Module      :  Database.TxtSushi.SQLFunctionDefinitions
-- Copyright   :  (c) <NAME> 2009
-- License     :  GPL3 or greater
-- Maintainer  :  <EMAIL>
-- Stability   :  experimental
-- Portability :  portable
--
-- SQL Functions
--
-----------------------------------------------------------------------------

module Database.TxtSushi.SQLFunctionDefinitions (
    SQLFunction(..),
    normalSyntaxFunctions,
    infixFunctions,
    specialFunctions,
    
    -- TODO remove these
    negateFunction,
    countFunction,
    substringFromToFunction,
    substringFromFunction,
    notFunction) where

import Data.Char
import Data.List
import Text.Regex.Posix

import Database.TxtSushi.EvaluatedExpression
import Database.TxtSushi.SQLExpression

-- Functions with "normal" syntax --
normalSyntaxFunctions :: [SQLFunction]
normalSyntaxFunctions =
    [absFunction, upperFunction, lowerFunction, trimFunction, ifThenElseFunction,
     -- all aggregates except count which accepts a (*)
     avgFunction, firstFunction, lastFunction, maxFunction,
     minFunction, sumFunction]

-- non aggregates
absFunction :: SQLFunction
absFunction = SQLFunction {
    functionName    = "ABS",
    minArgCount     = 1,
    argCountIsFixed = True,
    applyFunction   = applyUnaryNumeric absFunction abs abs}

upperFunction :: SQLFunction
upperFunction = SQLFunction {
    functionName    = "UPPER",
    minArgCount     = 1,
    argCountIsFixed = True,
    applyFunction   = applyUnaryString upperFunction (map toUpper)}

lowerFunction :: SQLFunction
lowerFunction = SQLFunction {
    functionName    = "LOWER",
    minArgCount     = 1,
    argCountIsFixed = True,
    applyFunction   = applyUnaryString lowerFunction (map toLower)}

trimFunction :: SQLFunction
trimFunction = SQLFunction {
    functionName    = "TRIM",
    minArgCount     = 1,
    argCountIsFixed = True,
    applyFunction   = applyUnaryString trimFunction trimSpace}

ifThenElseFunction :: SQLFunction
ifThenElseFunction = SQLFunction {
    functionName    = "IF_THEN_ELSE",
    minArgCount     = 3,
    argCountIsFixed = True,
    applyFunction   = ifThenElse . checkArgCount ifThenElseFunction}
    where
        ifThenElse [ifExpr, thenExpr, elseExpr] =
            if coerceBool ifExpr
            then thenExpr
            else elseExpr
        ifThenElse _ = internalError

-- aggregates
avgFunction :: SQLFunction
avgFunction = SQLFunction {
    functionName    = "AVG",
    minArgCount     = 1,
    argCountIsFixed = False,
    applyFunction   = avgFun . checkArgCount avgFunction}
    -- TODO this AVG(...) holds the whole arg list in memory. reimplement!
    where
        avgFun args = RealExpression $
            foldl1' (+) (map coerceReal args) /
            (fromIntegral $ length args)

countFunction :: SQLFunction
countFunction = SQLFunction {
    functionName    = "COUNT",
    minArgCount     = 0,
    argCountIsFixed = False,
    applyFunction   = IntExpression . length}

firstFunction :: SQLFunction
firstFunction = SQLFunction {
    functionName    = "FIRST",
    minArgCount     = 1,
    argCountIsFixed = False,
{'fraction_non_alphanumeric': 0.12785845434818896, 'fraction_numerical': 0.004506760140210316, 'mean_word_length': 2.528857479387515, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7578351', 'n_tokens_mistral': 1658, 'n_tokens_neox': 1592, 'n_words': 410}