txt-sushi 0.5.1 → 0.6.0
raw patch · 20 files changed
+209/−87 lines, 20 filessetup-changednew-component:exe:csvzip
Files
- Database/TxtSushi/CommandLineArgument.hs +0/−1
- Database/TxtSushi/EvaluatedExpression.hs +0/−1
- Database/TxtSushi/ExternalSort.hs +0/−1
- Database/TxtSushi/FlatFile.hs +0/−5
- Database/TxtSushi/IOUtil.hs +5/−7
- Database/TxtSushi/ParseUtil.hs +6/−6
- Database/TxtSushi/Relational.hs +38/−13
- Database/TxtSushi/SQLExecution.hs +32/−14
- Database/TxtSushi/SQLExpression.hs +7/−3
- Database/TxtSushi/SQLFunctionDefinitions.hs +10/−1
- Database/TxtSushi/SQLParser.hs +40/−16
- Setup.hs +5/−0
- csvtotab.hs +0/−1
- csvzip.hs +54/−0
- namecolumns.hs +0/−1
- tabtocsv.hs +0/−1
- transposecsv.hs +0/−1
- transposetab.hs +0/−1
- tssql.hs +0/−6
- txt-sushi.cabal +12/−8
Database/TxtSushi/CommandLineArgument.hs view
@@ -27,7 +27,6 @@ argumentCountIsFixed) where import Data.List-import Data.Map (Map) import qualified Data.Map as Map data CommandLineDescription = CommandLineDescription {
Database/TxtSushi/EvaluatedExpression.hs view
@@ -27,7 +27,6 @@ coerceBool) where import Data.Char-import Data.List import Data.Ord import Database.TxtSushi.ParseUtil
Database/TxtSushi/ExternalSort.hs view
@@ -17,7 +17,6 @@ defaultByteQuota, defaultMaxOpenFiles) where -import Control.Monad import Data.Binary import Data.Binary.Get import Data.Int
Database/TxtSushi/FlatFile.hs view
@@ -11,10 +11,6 @@ -- ----------------------------------------------------------------------------- -{- |-The 'FlatFile' module is for reading misc. 'FlatFile' formats like CSV or-tab delimited--} module Database.TxtSushi.FlatFile ( formatTableWithWidths, maxTableColumnWidths,@@ -25,7 +21,6 @@ tabDelimitedFormat, doubleQuote) where -import Data.Function import Data.List import Data.Ord
Database/TxtSushi/IOUtil.hs view
@@ -13,15 +13,15 @@ module Database.TxtSushi.IOUtil ( bufferStdioToTempFile, getContentsFromFileOrStdin,- printSingleFileUsage) where+ printSingleFileUsage,+ versionStr) where -import Data.List-import Data.Version (Version(..)) import System.Directory import System.Environment import System.IO -import Paths_txt_sushi+versionStr :: String+versionStr = "0.6.0" -- | buffers standard input to a temp file and returns a path to that file bufferStdioToTempFile :: IO FilePath@@ -48,6 +48,4 @@ progName <- getProgName putStrLn $ progName ++ " (" ++ versionStr ++ ")" putStrLn $ "Usage: " ++ progName ++ " file_name_or_dash"- - where- versionStr = intercalate "." (map show . versionBranch $ version)+
Database/TxtSushi/ParseUtil.hs view
@@ -40,7 +40,7 @@ anyParseTxt = signedParseTxt <|> unsignedParseTxt <?> "integer" unsignedParseTxt = many1 digit signedParseTxt = do- char '-'+ _ <- char '-' unsignedDigitTxt <- unsignedParseTxt return $ '-' : unsignedDigitTxt @@ -75,11 +75,11 @@ txtWithoutExponent = signedTxt <|> unsignedTxt <?> "real" unsignedTxt = do intTxt <- many1 digit- char '.'+ _ <- char '.' fracTxt <- many1 digit return $ intTxt ++ "." ++ fracTxt signedTxt = do- char '-'+ _ <- char '-' unsignedDigitTxt <- unsignedTxt return ('-':unsignedDigitTxt) @@ -101,10 +101,10 @@ let quote = char quoteChar manyFunc = if allowEmpty then many else many1 - quote+ _ <- quote textValue <- manyFunc $ (anyChar `genExcept` quote) <|> try (escapedQuote quoteChar)- quote+ _ <- quote spaces return textValue@@ -178,7 +178,7 @@ -- for lists greater than 1 we do need to care about the separator parseEach (headParser:parserTail) = do resultHead <- headParser- sepParser+ _ <- sepParser resultTail <- parseEach parserTail return $ resultHead:resultTail
Database/TxtSushi/Relational.hs view
@@ -11,9 +11,6 @@ -- ----------------------------------------------------------------------------- -{- |-Simple table transformations--} module Database.TxtSushi.Relational ( joinTables, crossJoinTables,@@ -34,21 +31,23 @@ sortedTable1 = sortBy (compare `on` joinOrdFunc1) table1 sortedTable2 = sortBy (compare `on` joinOrdFunc2) table2 in- joinPresortedTables joinOrdFunc1 sortedTable1 joinOrdFunc2 sortedTable2+ joinPresortedTables joinOrdFunc1 sortedTable1 Nothing joinOrdFunc2 sortedTable2 Nothing -- | join together two tables that are presorted on the given column index pairs joinPresortedTables :: (Ord o) => (a -> o) -> [a]+ -> Maybe a -> (b -> o) -> [b]+ -> Maybe b -> [(a, b)]-joinPresortedTables joinOrdFunc1 sortedTable1 joinOrdFunc2 sortedTable2 =+joinPresortedTables joinOrdFunc1 sortedTable1 maybeNull1 joinOrdFunc2 sortedTable2 maybeNull2 = let tableGroups1 = groupBy rowEq1 sortedTable1 tableGroups2 = groupBy rowEq2 sortedTable2 in- joinGroupedTables joinOrdFunc1 tableGroups1 joinOrdFunc2 tableGroups2+ joinGroupedTables joinOrdFunc1 tableGroups1 maybeNull1 joinOrdFunc2 tableGroups2 maybeNull2 where rowEq1 x y = (compare `on` joinOrdFunc1) x y == EQ rowEq2 x y = (compare `on` joinOrdFunc2) x y == EQ@@ -62,28 +61,54 @@ joinGroupedTables :: (Ord o) => (a -> o) -> [[a]]+ -> Maybe a -> (b -> o) -> [[b]]+ -> Maybe b -> [(a, b)]-joinGroupedTables _ [] _ _ = []-joinGroupedTables _ _ _ [] = []+joinGroupedTables _ [] Nothing _ _ _ = []+joinGroupedTables _ _ _ _ [] Nothing = []++joinGroupedTables _ [] (Just null1) _ tableGroups2 _ = zip (repeat null1) (concat tableGroups2)+joinGroupedTables _ tableGroups1 _ _ [] (Just null2) = zip (concat tableGroups1) (repeat null2)+ joinGroupedTables joinOrdFunc1 tableGroups1@(headTableGroup1:tableGroupsTail1)+ maybeNull1+ joinOrdFunc2- tableGroups2@(headTableGroup2:tableGroupsTail2) =+ tableGroups2@(headTableGroup2:tableGroupsTail2)+ maybeNull2 = let headRow1 = head headTableGroup1 headRow2 = head headTableGroup2 in case joinOrdFunc1 headRow1 `compare` joinOrdFunc2 headRow2 of -- drop the 1st group if its smaller- LT -> joinGroupedTables joinOrdFunc1 tableGroupsTail1 joinOrdFunc2 tableGroups2+ LT ->+ let joinRemainder =+ joinGroupedTables+ joinOrdFunc1 tableGroupsTail1 maybeNull1+ joinOrdFunc2 tableGroups2 maybeNull2 in+ case maybeNull2 of+ Nothing -> joinRemainder+ Just null2 -> zip headTableGroup1 (repeat null2) ++ joinRemainder -- drop the 2nd group if its smaller- GT -> joinGroupedTables joinOrdFunc1 tableGroups1 joinOrdFunc2 tableGroupsTail2+ GT ->+ let joinRemainder =+ joinGroupedTables+ joinOrdFunc1 tableGroups1 maybeNull1+ joinOrdFunc2 tableGroupsTail2 maybeNull2 in+ case maybeNull1 of+ Nothing -> joinRemainder+ Just null1 -> zip (repeat null1) headTableGroup2 ++ joinRemainder -- the two groups are equal so permute _ ->- (crossJoinTables headTableGroup1 headTableGroup2) ++- (joinGroupedTables joinOrdFunc1 tableGroupsTail1 joinOrdFunc2 tableGroupsTail2)+ let joinRemainder =+ joinGroupedTables+ joinOrdFunc1 tableGroupsTail1 maybeNull1+ joinOrdFunc2 tableGroupsTail2 maybeNull2 in+ crossJoinTables headTableGroup1 headTableGroup2 ++ joinRemainder
Database/TxtSushi/SQLExecution.hs view
@@ -20,13 +20,11 @@ import Control.Applicative import Data.Binary-import Data.Char import Data.Function import Data.List import qualified Data.Map as M import Database.TxtSushi.SQLExpression-import Database.TxtSushi.SQLFunctionDefinitions import Database.TxtSushi.EvaluatedExpression import Database.TxtSushi.ExternalSort import Database.TxtSushi.Relational@@ -50,7 +48,8 @@ qualifiedColumnsWithContext = M.empty, evaluationContext = evalCtxt, tableData = tblRows,- isInScope = idInHeader}+ isInScope = idInHeader,+ nullRow = replicate (length headerNames) ""} where makeColExpr colName = ColumnExpression (ColumnIdentifier Nothing colName) colName @@ -86,7 +85,8 @@ qualifiedColumnsWithContext = M.empty, evaluationContext = eval, tableData = [shouldNeverOccurError] :: [String],- isInScope = const False}+ isInScope = const False,+ nullRow = []} where eval (ColumnExpression _ colStr) = columnNotInScopeError colStr eval expr = evalWithContext eval expr@@ -157,16 +157,24 @@ let table = M.findWithDefault (tableNotInScopeError tblName) tblName tableMap in maybeRename maybeTblAlias table - -- TODO inner join should allow joining on expressions too!! InnerJoin leftJoinTblExpr rightJoinTblExpr onConditionExpr maybeTblAlias -> let leftJoinTbl = evalTableExpression sortCfg leftJoinTblExpr tableMap rightJoinTbl = evalTableExpression sortCfg rightJoinTblExpr tableMap joinExprs = extractJoinExprs leftJoinTbl rightJoinTbl onConditionExpr- joinedTbl = innerJoinDbTables sortCfg joinExprs leftJoinTbl rightJoinTbl+ joinedTbl = sortAndJoinDbTables False sortCfg joinExprs leftJoinTbl rightJoinTbl in maybeRename maybeTblAlias joinedTbl + OuterJoin leftJoinTblExpr rightJoinTblExpr onConditionExpr maybeTblAlias ->+ let+ leftJoinTbl = evalTableExpression sortCfg leftJoinTblExpr tableMap+ rightJoinTbl = evalTableExpression sortCfg rightJoinTblExpr tableMap+ joinExprs = extractJoinExprs leftJoinTbl rightJoinTbl onConditionExpr+ joinedTbl = sortAndJoinDbTables True sortCfg joinExprs leftJoinTbl rightJoinTbl+ in+ maybeRename maybeTblAlias joinedTbl+ SelectExpression selectStmt maybeTblAlias -> maybeRename maybeTblAlias (select sortCfg selectStmt tableMap) @@ -330,7 +338,10 @@ tableData :: [a], -- | is the given identifier in scope for this table- isInScope :: ColumnIdentifier -> Bool}+ isInScope :: ColumnIdentifier -> Bool,+ + -- | we can only do an outer join if the concept of a NULL row exists+ nullRow :: a} allIdentifiers :: Expression -> [ColumnIdentifier] allIdentifiers (FunctionExpression _ args _) = concatMap allIdentifiers args@@ -433,7 +444,8 @@ columnsWithContext = mapSnd toGroupContext (columnsWithContext tbl), qualifiedColumnsWithContext = M.map (mapSnd toGroupContext) (qualifiedColumnsWithContext tbl), evaluationContext = toGroupContext $ evaluationContext tbl,- tableData = groupedData}+ tableData = groupedData,+ nullRow = [nullRow tbl]} where eval = evaluationContext tbl rowOrd row = [eval expr row | expr <- grpExprs]@@ -448,7 +460,8 @@ columnsWithContext = mapSnd toGroupContext (columnsWithContext tbl), qualifiedColumnsWithContext = M.map (mapSnd toGroupContext) (qualifiedColumnsWithContext tbl), evaluationContext = toGroupContext $ evaluationContext tbl,- tableData = [tableData tbl]}+ tableData = [tableData tbl],+ nullRow = [nullRow tbl]} compareWithDirection :: (Ord a) => [Bool] -> [a] -> [a] -> Ordering compareWithDirection (asc:ascTail) (x:xt) (y:yt) = case x `compare` y of@@ -458,13 +471,14 @@ compareWithDirection [] [] [] = EQ compareWithDirection _ _ _ = error "Internal Error: List sizes should match" -innerJoinDbTables ::- SortConfiguration+sortAndJoinDbTables ::+ Bool+ -> SortConfiguration -> [(Expression, Expression)] -> BoxedTable -> BoxedTable -> BoxedTable-innerJoinDbTables sortCfg joinExprs (BoxedTable fstTable) (BoxedTable sndTable) =+sortAndJoinDbTables outerJoin sortCfg joinExprs (BoxedTable fstTable) (BoxedTable sndTable) = BoxedTable $ zipDbTables joinedData fstTable sndTable where fstEval = evaluationContext fstTable@@ -476,7 +490,10 @@ sortedFstData = sortByCfg sortCfg (compare `on` fstRowOrd) (tableData fstTable) sortedSndData = sortByCfg sortCfg (compare `on` sndRowOrd) (tableData sndTable) - joinedData = joinPresortedTables fstRowOrd sortedFstData sndRowOrd sortedSndData+ fstNull = if outerJoin then Just (nullRow fstTable) else Nothing+ sndNull = if outerJoin then Just (nullRow sndTable) else Nothing+ + joinedData = joinPresortedTables fstRowOrd sortedFstData fstNull sndRowOrd sortedSndData sndNull crossJoinDbTables :: BoxedTable@@ -493,7 +510,8 @@ qualifiedColumnsWithContext = M.unionWithKey ambiguousTableError fstQualCols sndQualCols, evaluationContext = evalCtxt, tableData = zippedData,- isInScope = isInFstOrSndScope}+ isInScope = isInFstOrSndScope,+ nullRow = (nullRow fstTable, nullRow sndTable)} where isInFstScope = isInScope fstTable
Database/TxtSushi/SQLExpression.hs view
@@ -26,9 +26,6 @@ expressionToString, columnToString) where -import Data.Char-import Data.List- import Database.TxtSushi.EvaluatedExpression --------------------------------------------------------------------------------@@ -53,6 +50,11 @@ rightJoinTable :: TableExpression, onCondition :: Expression, maybeTableAlias :: Maybe String} |+ OuterJoin {+ leftJoinTable :: TableExpression,+ rightJoinTable :: TableExpression,+ onCondition :: Expression,+ maybeTableAlias :: Maybe String} | CrossJoin { leftJoinTable :: TableExpression, rightJoinTable :: TableExpression,@@ -70,6 +72,8 @@ allTableNames :: TableExpression -> [String] allTableNames (TableIdentifier tblName _) = [tblName] allTableNames (InnerJoin lftTbl rtTbl _ _) =+ (allTableNames lftTbl) ++ (allTableNames rtTbl)+allTableNames (OuterJoin lftTbl rtTbl _ _) = (allTableNames lftTbl) ++ (allTableNames rtTbl) allTableNames (CrossJoin lftTbl rtTbl _) = (allTableNames lftTbl) ++ (allTableNames rtTbl)
Database/TxtSushi/SQLFunctionDefinitions.hs view
@@ -36,7 +36,7 @@ -- Functions with "normal" syntax -- normalSyntaxFunctions :: [SQLFunction] normalSyntaxFunctions =- [absFunction, upperFunction, lowerFunction, trimFunction, ifThenElseFunction,+ [absFunction, upperFunction, lowerFunction, trimFunction, lengthFunction, ifThenElseFunction, asIntFunction, asRealFunction, isNumericFunction, -- all aggregates except count which accepts a (*) avgFunction, firstFunction, lastFunction, maxFunction,@@ -110,6 +110,15 @@ applyFunction = applyUnaryString trimFunction trimSpace, functionGrammar = normalGrammar trimFunction, functionDescription = "trims whitespace from the beginning and end of the given text"}++lengthFunction :: SQLFunction+lengthFunction = SQLFunction {+ functionName = "LEN",+ minArgCount = 1,+ argCountIsFixed = True,+ applyFunction = IntExpression . length . coerceString . head . checkArgCount lengthFunction,+ functionGrammar = normalGrammar lengthFunction,+ functionDescription = "the number of characters in the given text"} ifThenElseFunction :: SQLFunction ifThenElseFunction = SQLFunction {
Database/TxtSushi/SQLParser.hs view
@@ -129,11 +129,11 @@ parseRangeColumns = parseRangeInner where parseRangeInner = do- parseToken "FOR"+ _ <- parseToken "FOR" bindingId <- parseColumnId- parseToken "IN"+ _ <- parseToken "IN" colRange <- parseColRange- parseToken "YIELD"+ _ <- parseToken "YIELD" expr <- parseExpression return $ ExpressionColumnRange bindingId colRange expr@@ -141,7 +141,7 @@ where parseColRange = brace $ do maybeStartCol <- maybeParse parseColumnId- parseToken ".."+ _ <- parseToken ".." maybeEndCol <- maybeParse parseColumnId return $ ColumnRange maybeStartCol maybeEndCol@@ -152,7 +152,7 @@ parseAllColsFromTbl :: GenParser Char st ColumnSelection parseAllColsFromTbl = do tableVal <- parseIdentifier- string "." >> spaces >> parseToken "*"+ _ <- string "." >> spaces >> parseToken "*" return $ AllColumnsFrom tableVal @@ -197,6 +197,14 @@ nextTblId <- parseTableIdentifier let+ ifJoinParse = ifParseThenElse+ -- if+ outerJoinSep -- TODO commit to join+ -- then+ (parseOuterJoinRemainder nextTblId)+ --else+ ifCrossOrInnerJoinParse+ ifCrossOrInnerJoinParse = ifParseThenElse -- if crossJoinSep -- TODO commit to join@@ -213,9 +221,10 @@ -- else (return nextTblId) - ifCrossOrInnerJoinParse+ ifJoinParse where+ outerJoinSep = parseToken "OUTER" >> parseToken "JOIN" crossJoinSep = (commaSeparator >> return "") <|> (parseToken "CROSS" >> parseToken "JOIN") innerJoinSep = ((maybeParse $ parseToken "INNER") >> parseToken "JOIN") @@ -223,7 +232,7 @@ parseInnerJoinRemainder leftTblExpr = do rightTblExpr <- parseTableExpression - parseToken "ON"+ _ <- parseToken "ON" onPart <- parseExpression maybeAlias <- maybeParseAlias@@ -234,6 +243,21 @@ onCondition=onPart, maybeTableAlias=maybeAlias} +parseOuterJoinRemainder :: TableExpression -> GenParser Char a TableExpression+parseOuterJoinRemainder leftTblExpr = do+ rightTblExpr <- parseTableExpression+ + _ <- parseToken "ON"+ onPart <- parseExpression+ + maybeAlias <- maybeParseAlias+ + return OuterJoin {+ leftJoinTable=leftTblExpr,+ rightJoinTable=rightTblExpr,+ onCondition=onPart,+ maybeTableAlias=maybeAlias}+ parseCrossJoinRemainder :: TableExpression -> GenParser Char a TableExpression parseCrossJoinRemainder leftTblExpr = do rightTblExpr <- parseTableExpression@@ -335,12 +359,12 @@ parseSubstringFunction :: GenParser Char st Expression parseSubstringFunction = do funcStr <- parseToken $ functionName substringFromFunction- eatSpacesAfter $ char '('+ _ <- eatSpacesAfter $ char '(' strExpr <- parseExpression fromStr <- parseToken "FROM" startExpr <- parseExpression maybeForStrAndLength <- preservingIfParseThen (parseToken "FOR") parseExpression- eatSpacesAfter $ char ')'+ _ <- eatSpacesAfter $ char ')' let funcStrStart = funcStr ++ "(" ++ expressionToString strExpr ++ " " ++@@ -373,7 +397,7 @@ parseCountStar :: GenParser Char st Expression parseCountStar = do funcStr <- try (parseToken $ functionName countFunction)- parenthesize (parseToken "*")+ _ <- parenthesize (parseToken "*") return $ FunctionExpression countFunction [IntConstantExpression 0 "*"] (funcStr ++ "(*)") @@ -417,17 +441,17 @@ -- | Wraps braces parsers around the given inner parser brace :: GenParser Char st a -> GenParser Char st a brace innerParser = do- eatSpacesAfter $ char '['+ _ <- eatSpacesAfter $ char '[' innerParseResults <- innerParser- eatSpacesAfter $ char ']'+ _ <- eatSpacesAfter $ char ']' return innerParseResults -- | Wraps parentheses parsers around the given inner parser parenthesize :: GenParser Char st a -> GenParser Char st a parenthesize innerParser = do- eatSpacesAfter $ char '('+ _ <- eatSpacesAfter $ char '(' innerParseResults <- innerParser- eatSpacesAfter $ char ')'+ _ <- eatSpacesAfter $ char ')' return innerParseResults parseReservedWord :: GenParser Char st String@@ -441,8 +465,8 @@ map functionName normalSyntaxFunctions ++ map functionName (concat infixFunctions) ++ map functionName specialFunctions ++- ["BY","CROSS", "FROM", "FOR", "GROUP", "HAVING", "IN", "INNER", "JOIN", "ON",- "ORDER", "SELECT", "WHERE", "TRUE", "FALSE", "YIELD"]+ ["BY", "CROSS", "FROM", "FOR", "GROUP", "HAVING", "IN", "INNER", "JOIN", "ON",+ "ORDER", "OUTER", "SELECT", "WHERE", "TRUE", "FALSE", "YIELD"] -- | tries parsing both the upper and lower case versions of the given string upperOrLower :: String -> GenParser Char st String
Setup.hs view
@@ -1,2 +1,7 @@+module Main (main) where+ import Distribution.Simple++main :: IO () main = defaultMain+
csvtotab.hs view
@@ -11,7 +11,6 @@ -- ----------------------------------------------------------------------------- import System.Environment-import System.IO import Database.TxtSushi.FlatFile import Database.TxtSushi.IOUtil
+ csvzip.hs view
@@ -0,0 +1,54 @@+-----------------------------------------------------------------------------+-- |+-- Module : csvzip+-- Copyright : (c) Keith Sheppard 2009-2010+-- License : BSD3+-- Maintainer : keithshep@gmail.com+-- Stability : experimental+-- Portability : portable+--+-- Joins CSV files by pasting the columns together. Analogous to cbind for+-- those familliar with the R programming language. This utility streams+-- data so it can work on very large files. If the table row lengths don't+-- match then the shorter tables will be padded with empty cells.+--+-----------------------------------------------------------------------------+import System.Environment (getArgs, getProgName)++import Database.TxtSushi.FlatFile (csvFormat, formatTable, parseTable)+import Database.TxtSushi.IOUtil (getContentsFromFileOrStdin, versionStr)++main :: IO ()+main = do+ fileNames <- getArgs+ + case fileNames of+ -- parse all CSV files giving us a list of tables, then zip and print them+ (_ : _ : _) -> do+ tables <- mapM getAndParseTable fileNames+ putStr $ formatTable csvFormat (zipAllColumns tables)+ + _ -> printUsage++-- | read the contents of the given files name and parse it as a CSV file+getAndParseTable :: String -> IO [[String]]+getAndParseTable = fmap (parseTable csvFormat) . getContentsFromFileOrStdin++-- | zips together the columns of a non-empty list of tables+zipAllColumns :: [[[String]]] -> [[String]]+zipAllColumns = foldl1 (zipCols [] [])+ where+ -- if row counts don't match we pad the table that fell short with empty cells+ zipCols _ _ (x:xt) (y:yt) = (x ++ y) : zipCols x y xt yt+ zipCols _ _ [] [] = []+ zipCols _ prevY xs [] = zipWith (++) xs (padCols prevY)+ zipCols prevX _ [] ys = zipWith (++) (padCols prevX) ys+ + padCols lastRow = repeat (replicate (length lastRow) "")++printUsage :: IO ()+printUsage = do+ progName <- getProgName+ putStrLn $ progName ++ " (" ++ versionStr ++ ")"+ putStrLn $ "Usage: " ++ progName ++ " csvfile_or_dash csvfile_or_dash ..."+
namecolumns.hs view
@@ -11,7 +11,6 @@ -- ----------------------------------------------------------------------------- import System.Environment-import System.IO import Database.TxtSushi.FlatFile import Database.TxtSushi.IOUtil
tabtocsv.hs view
@@ -11,7 +11,6 @@ -- ----------------------------------------------------------------------------- import System.Environment-import System.IO import Database.TxtSushi.FlatFile import Database.TxtSushi.IOUtil
transposecsv.hs view
@@ -12,7 +12,6 @@ ----------------------------------------------------------------------------- import Data.List import System.Environment-import System.IO import Database.TxtSushi.FlatFile import Database.TxtSushi.IOUtil
transposetab.hs view
@@ -12,7 +12,6 @@ ----------------------------------------------------------------------------- import Data.List import System.Environment-import System.IO import Database.TxtSushi.FlatFile import Database.TxtSushi.IOUtil
tssql.hs view
@@ -11,11 +11,9 @@ ----------------------------------------------------------------------------- import Data.Char import Data.List-import Data.Version (Version(..)) import qualified Data.Map as M import System.Environment import System.Exit-import System.IO import Text.ParserCombinators.Parsec @@ -27,8 +25,6 @@ import Database.TxtSushi.SQLFunctionDefinitions import Database.TxtSushi.SQLParser -import Paths_txt_sushi- helpOption :: OptionDescription helpOption = OptionDescription { isRequired = False,@@ -93,8 +89,6 @@ printUsage progName = do putStrLn $ progName ++ " (" ++ versionStr ++ ")" putStrLn $ "Usage: " ++ progName ++ " " ++ formatCommandLine sqlCmdLine- where- versionStr = intercalate "." (map show $ versionBranch version) argsToSortConfig :: M.Map OptionDescription a -> SortConfiguration argsToSortConfig argMap =
txt-sushi.cabal view
@@ -1,8 +1,8 @@ Name: txt-sushi-Version: 0.5.1+Version: 0.6.0 Synopsis: The SQL link in your *NIX chain Description:- TxtSushi is a collection of command line utilities for processing+ txt-sushi is a collection of command line utilities for processing comma-separated and tab-delimited files (AKA flat files, spreadsheets). The most important utility (tssql) lets you perform SQL selects on CSV files. By focusing exclusively on processing text files with a tabular structure,@@ -14,19 +14,19 @@ Author: Keith Sheppard Maintainer: keithshep@gmail.com Homepage: http://keithsheppard.name/txt-sushi-Bug-Reports: http://code.google.com/p/txt-sushi/issues/list+Bug-Reports: https://github.com/keithshep/txt-sushi/issues Build-Type: Simple Category: Database, Console Cabal-Version: >= 1.6 Source-Repository head- type: darcs- location: http://patch-tag.com/r/keithshep/txt-sushi/pullrepo+ type: git+ location: git://github.com/keithshep/txt-sushi.git Source-Repository this- type: darcs- location: http://patch-tag.com/r/keithshep/txt-sushi/pullrepo- tag: 0.5.1+ type: git+ location: git://github.com/keithshep/txt-sushi.git+ tag: 0.6.0 Executable tssql Main-Is: tssql.hs@@ -61,6 +61,10 @@ Executable transposetab Main-Is: transposetab.hs+ GHC-Options: -O2 -Wall++Executable csvzip+ Main-Is: csvzip.hs GHC-Options: -O2 -Wall Library