-- $Id: scabies_load.sql,v 1.2 2008-10-29 17:30:31 jo Exp $
-- Licensed under the GPL. Copyright 2008 Joachim Zobel.
-- -----------------------------------------------------------------------
-- Straight table loads. Some fields are updated later, since subqueries
-- in LOAD DATA statements don't give a reasonable performance. Much
-- work is however done during the load, since the load is iobound.
--
-- USAGE: You need to replace $outdir with the directory that holds the
-- files generate by the parse script. Eg.:
-- sed 's#$outdir#/home/joe/data/OSM/output#' scabies_load.sql \
--    | mysql -u osm -p openstreetmap
-- Note that the mysql server reads those files. This means that the 
-- script needs to run on the server host, you need to use the full 
-- path and the mysql user needs read access. If this is not possible
-- try changing the script to use LOAD DATA LOCAL.
-- -----------------------------------------------------------------------

-- -----------------------------------------------------------------------
-- Setting variables
-- Note that this has to be done for every session if you split 
-- the script up for parallel loads or if execution was interrupted.
-- -----------------------------------------------------------------------

-- Consider this after reading its docs
-- SET GLOBAL innodb_flush_log_at_trx_commit = 2;

SET character_set_database = 'utf8';

-- -----------------------------------------------------------------------
-- Helpers
-- -----------------------------------------------------------------------

DELIMITER //

DROP FUNCTION IF EXISTS osm_parse_timestamp //

-- Work around http://bugs.mysql.com/40374
CREATE
FUNCTION osm_parse_timestamp(in_timestamp VARCHAR(32)) 
RETURNS DATETIME
DETERMINISTIC
BEGIN
  DECLARE pos       TINYINT DEFAULT 0;
  DECLARE tz_stamp  VARCHAR(32) DEFAULT '+00:00';

  -- Find a +
  SET pos = LOCATE('+', in_timestamp);
  IF pos = 0 THEN 
    -- Try finding - instead
    SET pos = LOCATE('-', in_timestamp);
  END IF; 

  IF pos = 0 THEN 
    -- Set tz_stamp to the found timezone
    SET tz_stamp = SUBSTR(in_timestamp, pos);
  END IF; 

  RETURN CONVERT_TZ(SUBSTR(in_timestamp, 1, SUBSTR(in_timestamp, 1, pos - 1)),
                    tz_stamp,
                    'SYSTEM');

END//

DELIMITER ;

-- -----------------------------------------------------------------------
-- Loading ....
-- -----------------------------------------------------------------------

LOAD DATA INFILE '$outdir/nodes.txt'
      INTO TABLE current_nodes
      (@ID, @LAT, @LON, @USER, @VISIBLE, 
       @TIMESTAMP)
      SET id = @ID,
          latitude = @LAT*10000000,
          longitude = @LON*10000000,
          user_id = -1,
          visible = IF(IFNULL(@VISIBLE, 'true') = 'true', 1, 0),
          tags = '',
          timestamp = osm_parse_timestamp(@TIMESTAMP),
          tile = (CONV(BIN(FLOOR(0.5 + 65535*(@LON+180)/360)), 4, 10)<<1) 
                  | CONV(BIN(FLOOR(0.5 + 65535*(@LAT+90)/180)), 4, 10); 

LOAD DATA INFILE '$outdir/ways.txt'
      INTO TABLE current_ways
      (id, @USER, @TIMESTAMP, @VISIBLE)
      SET user_id = -1,
          timestamp = osm_parse_timestamp(@TIMESTAMP),
          visible = IF(IFNULL(@VISIBLE, 'true') = 'true', 1, 0);

LOAD DATA INFILE '$outdir/way_tags.txt'
          IGNORE
      INTO TABLE current_way_tags
      (id, k, v);

SET @CNT = 1;
SET @PREV_ID = -1;
LOAD DATA INFILE '$outdir/way_nodes.txt'
      INTO TABLE current_way_nodes
      (@ID, node_id)
      SET id = @ID,
          sequence_id = IF(@ID = @PREV_ID, @CNT := @CNT + 1, @CNT := 1 +
                                                             0*(@PREV_ID := @ID));

-- -----------------------------------------------------------------------
-- Set the node tags. This requires a helper table. Hopefully this way of 
-- storing node tags will be replaced by something that looks like our 
-- helper table in 0.6.
-- -----------------------------------------------------------------------


CREATE TABLE node_tags (
  id BIGINT NOT NULL,
  k VARCHAR(255) NOT NULL,
  v TEXT NOT NULL default '',
  KEY current_way_tags_id_idx (id)
) 
ENGINE=InnoDb 
CHARSET=utf8;

-- Unfortunately this is not true 
-- ALTER TABLE node_tags
-- ADD PRIMARY KEY node_tags_pk(id, k);

LOAD DATA INFILE '$outdir/node_tags.txt'
      INTO TABLE node_tags
      (id, k, v);

SET group_concat_max_len = 65535;

   UPDATE current_nodes n
       SET n.tags = (SELECT GROUP_CONCAT(CONCAT(k,'=',
                                             REPLACE(
                                             REPLACE(v, ';', ';;;'),
                                                        '=', '==='))
                                                     SEPARATOR ';') AS tags
                       FROM node_tags nt
                      WHERE nt.id = n.id);

DROP TABLE node_tags;

-- -----------------------------------------------------------------------
-- relations
-- -----------------------------------------------------------------------

LOAD DATA INFILE '$outdir/relations.txt'
      INTO TABLE current_relations
      (@ID, @USER, @TIMESTAMP, @VISIBLE)
      SET id = @ID,
          user_id = -1,
          visible = IF(IFNULL(@VISIBLE, 'true') = 'true', 1, 0),
          timestamp = osm_parse_timestamp(@TIMESTAMP);

LOAD DATA INFILE '$outdir/relation_members.txt'
      INTO TABLE current_relation_members
      (id, member_type, member_id, member_role);

LOAD DATA INFILE '$outdir/relation_tags.txt'
      INTO TABLE current_relation_tags
      (id, k, v);

-- -----------------------------------------------------------------------
-- Set user field. This unfortunately requires helper tables.
-- -----------------------------------------------------------------------

-- -----------------------------------------------------------------------
-- Users from nodes
-- -----------------------------------------------------------------------


CREATE TABLE node_users 
ENGINE=InnoDb 
CHARSET=utf8
AS
   SELECT n.id, u.display_name 
     FROM current_nodes n, users u
    WHERE 1 = 0;

ALTER TABLE node_users ADD
  PRIMARY KEY (id);

LOAD DATA INFILE '$outdir/nodes.txt'
      INTO TABLE node_users
      (id, @DUMMY, @DUMMY, display_name, 
       @DUMMY, @DUMMY, @DUMMY);

      -- Write them to the users table
  INSERT INTO users(email, display_name, pass_crypt, creation_time, description)
  SELECT display_name, display_name, MD5(display_name), NOW(), ''
    FROM node_users
GROUP BY display_name;

  UPDATE current_nodes n
    JOIN node_users nu
      ON nu.id = n.id
    JOIN users u 
      ON u.display_name = nu.display_name
     SET n.user_id = u.id;

-- No longer needed
DROP TABLE node_users;

-- -----------------------------------------------------------------------
-- users from ways
-- -----------------------------------------------------------------------


CREATE TABLE way_users 
ENGINE=InnoDb 
CHARSET=utf8
AS
   SELECT n.id, u.display_name 
     FROM current_ways n, users u
    WHERE 1 = 0;

ALTER TABLE way_users ADD
  PRIMARY KEY (id);


LOAD DATA INFILE '$outdir/ways.txt'
          IGNORE
      INTO TABLE way_users
      (id, display_name, @DUMMY, @DUMMY);

      -- Write the ones that are only in ways
  INSERT IGNORE users(email, display_name, pass_crypt, creation_time, description)
  SELECT display_name, display_name, MD5(display_name), NOW(), ''
    FROM way_users
GROUP BY display_name;

  UPDATE current_ways w
    JOIN way_users wu
      ON wu.id = w.id
    JOIN users u 
      ON u.display_name = wu.display_name
     SET w.user_id = u.id;

-- No longer needed
DROP TABLE way_users;

-- -----------------------------------------------------------------------
-- Users from relations
-- -----------------------------------------------------------------------


CREATE TABLE relation_users 
ENGINE=InnoDb 
CHARSET=utf8
AS
   SELECT n.id, u.display_name 
     FROM current_relations n, users u
    WHERE 1 = 0;

ALTER TABLE relation_users ADD
  PRIMARY KEY (id);

LOAD DATA INFILE '$outdir/relations.txt'
      INTO TABLE relation_users
      (id, display_name, @DUMMY, @DUMMY);

      -- Write them to the users table
  INSERT IGNORE users(email, display_name, pass_crypt, creation_time, description)
  SELECT display_name, display_name, MD5(display_name), NOW(), ''
    FROM relation_users
GROUP BY display_name;

  UPDATE current_relations n
    JOIN relation_users nu
      ON nu.id = n.id
    JOIN users u 
      ON u.display_name = nu.display_name
     SET n.user_id = u.id;

-- No longer needed
DROP TABLE relation_users;

-- No longer needed.
DROP FUNCTION IF EXISTS osm_parse_timestamp;

