+ dbmigrate _=
+ run_dbmigrate $ do
+ migrate (undefined :: Team)
+ migrate (undefined :: Odds)
+ migrate (undefined :: OddsCasino)
+ migrate (undefined :: OddsGame)
+ migrate (undefined :: OddsGameLine)
+
+ dbimport m = do
+ -- Insert the root "odds" element and acquire its primary key (id).
+ odds_id <- insert_xml m
+
+ forM_ (xml_games m) $ \game -> do
+ -- First we insert the home and away teams.
+ away_team_id <- insert_xml_or_select (xml_away_team game)
+ home_team_id <- insert_xml_or_select (xml_home_team game)
+
+ -- Now insert the game, keyed to the "odds" and its teams.
+ game_id <- insert_xml_fk_teams odds_id away_team_id home_team_id game
+
+ -- Finally, we insert the lines. The over/under entries for this
+ -- game and the lines for the casinos all wind up in the same
+ -- table, odds_games_lines. We can insert the over/under entries
+ -- freely with empty away/home lines.
+ --
+ -- Before we continue, we drop all casinos that are missing
+ -- either a client_id or name field.
+ --
+ let ou_casinos = filter nonempty_casino $ xml_over_under_casinos game
+
+ forM_ ou_casinos $ \c ->
+ -- Since we already filtered out the casinos without a
+ -- client_id or a name, the database conversion should always
+ -- return (Just something).
+ case (from_xml c) of
+ Nothing -> return () -- Should never happen, we filtered them out.
+ Just casino -> do
+ -- Start by inserting the casino.
+ ou_casino_id <- insert_or_select casino
+
+ -- Now add the over/under entry with the casino's id.
+ let ogl = OddsGameLine {
+ ogl_odds_games_id = game_id,
+ ogl_odds_casinos_id = ou_casino_id,
+ ogl_over_under = (xml_casino_line c),
+ ogl_away_line = Nothing,
+ ogl_home_line = Nothing }
+
+ insert_ ogl
+
+ -- ...but then when we insert the home/away team lines, we
+ -- prefer to update the existing entry rather than overwrite it
+ -- or add a new record.
+ let away_casinos = filter nonempty_casino $
+ xml_team_casinos (xml_away_team game)
+
+ forM_ away_casinos $ \c ->
+ case (from_xml c) of
+ Nothing -> return () -- Should never happen, we filtered them out.
+ Just casino -> do
+ -- insert, or more likely retrieve the existing, casino
+ a_casino_id <- insert_or_select casino
+
+ -- Get a Maybe Double instead of the Maybe String that's in there.
+ let away_line = home_away_line c
+
+ -- Unconditionally update that casino's away team line with ours.
+ update [Ogl_Away_Line =. away_line] $ -- WHERE
+ Ogl_Odds_Casinos_Id ==. a_casino_id
+
+ -- Repeat all that for the home team.
+ let home_casinos = filter nonempty_casino $
+ xml_team_casinos (xml_home_team game)
+
+ forM_ home_casinos $ \c ->
+ case (from_xml c) of
+ Nothing -> return () -- Should never happen, we filtered them out.
+ Just casino -> do
+ h_casino_id <- insert_or_select casino
+ let home_line = home_away_line c
+ update [Ogl_Home_Line =. home_line] $ -- WHERE
+ Ogl_Odds_Casinos_Id ==. h_casino_id
+
+ return game_id
+
+ return ImportSucceeded
+
+ where
+ nonempty_casino :: OddsGameCasinoXml -> Bool
+ nonempty_casino (OddsGameCasinoXml Nothing _ _) = False
+ nonempty_casino (OddsGameCasinoXml _ Nothing _) = False
+ nonempty_casino _ = True
+
+--
+-- Pickling
+--