1

Sorry for dumb question.

I have some kind of SQL schema, that looks like this (for example):

create table test_table (
    id integer not null,
    title text,
    primary key ("id")
);

create table test_table2 (
    id integer not null,
    subtitle text,
    some_wierd_count integer not null,
    primary key ("id")
);

From this schema I need only some information. I don't care about primary keys, indeces, "not null"s. Just table name, fields names and types.

I wrote following ugly code, that doesn't work: http://code.sdfgh153.ru/gimme-models/src/1e5a17f2f8dbc225b0d26da405f5a1303f896ddb/src/GimmeModels/Schema/SQLSchema/Parser.hs?at=default

As I thought this code should fill in this types:

data Schema = Schema { schemaTables :: [Table] } deriving (Show)

data Table = Table {
      tableName   :: String 
    , tableFields :: [Field]
    } deriving (Show)

data Field = Field {
      fieldName :: String
    , fieldType :: String
    } deriving (Show)

But can't figure it out, how to properly parse fields section inside create table expression. How should I detect end of field declaration?

Semyon Novikov
  • 261
  • 4
  • 10
  • 2
    Attoparsec gives you the `sepBy` combinator, that takes two parsers: one for the fields and one for the separators. Does that help? – kqr Nov 20 '13 at 13:46
  • It would be really cool to see some example of using `sepBy`. – Semyon Novikov Nov 20 '13 at 14:48
  • 1
    Unbeleivable, looks like it works. Thanks! Final code here: http://code.sdfgh153.ru/gimme-models/src/dd347efa153927fd07d6c9ff03f18d85b0584472/src/GimmeModels/Schema/SQLSchema/Parser.hs?at=default – Semyon Novikov Nov 20 '13 at 15:08
  • 1
    This is in Parsec, but it should be something similar for Attoparsec. `parse (sepBy (many (noneOf ",")) (char ',')) "" "things separated,by,commas"` which gives me `Right ["things separated","by","commas"]`. – kqr Nov 20 '13 at 15:16
  • 2
    Semyon: You should post an answer to your own question describing what you did and accept that, for future google people! – kqr Nov 20 '13 at 15:17
  • Be aware - a simple sepBy ',' isn't going to work for all possible column definitions. Might well work fine for your particular schema(s) though. – Richard Huxton Nov 20 '13 at 20:47

1 Answers1

1

Ok, with kelp of kqr I finally realized: I should use sepBy combinator. My final code to parse table with fields declarations:

tableParser :: P.Parser Table
tableParser = do
    P.manyTill P.anyChar $ P.stringCI "create table"
    P.skipWhile fieldGarbage
    n <- P.takeWhile (not . fieldGarbage)
    P.skipWhile fieldGarbage 
    P.char '(' 
    fs <- fieldParser `P.sepBy` P.char ','
    P.manyTill P.anyChar (P.char ';')
    return $ Table (C.unpack n) fs 

parseStr = do 
    P.skipWhile fieldGarbage
    P.takeWhile (not . fieldGarbage)

fieldParser :: P.Parser Field
fieldParser = do
    n <- parseStr
    t <- parseStr 
    P.takeTill (\c -> c == ',' || c == ';')
    return $ Field (C.unpack n) (C.unpack t)

Thank you all for the help.

Alex
  • 8,093
  • 6
  • 49
  • 79
Semyon Novikov
  • 261
  • 4
  • 10