]> git.openstreetmap.org Git - nominatim.git/blob - utils/setup.php
more partitioning work, os open data postcodes, country list fixes
[nominatim.git] / utils / setup.php
1 #!/usr/bin/php -Cq
2 <?php
3
4         require_once(dirname(dirname(__FILE__)).'/lib/init-cmd.php');
5         ini_set('memory_limit', '800M');
6
7         $aCMDOptions = array(
8                 "Create and setup nominatim search system",
9                 array('help', 'h', 0, 1, 0, 0, false, 'Show Help'),
10                 array('quiet', 'q', 0, 1, 0, 0, 'bool', 'Quiet output'),
11                 array('verbose', 'v', 0, 1, 0, 0, 'bool', 'Verbose output'),
12
13                 array('all', '', 0, 1, 1, 1, 'realpath', 'Do the complete process'),
14
15                 array('create-db', '', 0, 1, 0, 0, 'bool', 'Create nominatim db'),
16                 array('setup-db', '', 0, 1, 0, 0, 'bool', 'Build a blank nominatim db'),
17                 array('import-data', '', 0, 1, 1, 1, 'realpath', 'Import a osm file'),
18                 array('create-functions', '', 0, 1, 0, 0, 'bool', 'Create functions'),
19                 array('create-tables', '', 0, 1, 0, 0, 'bool', 'Create main tables'),
20                 array('create-partitions', '', 0, 1, 0, 0, 'bool', 'Create required partition tables and triggers'),
21                 array('load-data', '', 0, 1, 0, 0, 'bool', 'Copy data to live tables from import table'),
22         );
23         getCmdOpt($_SERVER['argv'], $aCMDOptions, $aCMDResult, true, true);
24
25         $bDidSomething = false;
26
27         if ($aCMDResult['create-db'] || isset($aCMDResult['all']))
28         {
29                 $bDidSomething = true;
30                 $oDB =& DB::connect(CONST_Database_DSN, false);
31                 if (!PEAR::isError($oDB))
32                 {
33                         fail('database already exists');
34                 }
35                 passthru('createdb nominatim');
36         }
37
38         if ($aCMDResult['create-db'] || isset($aCMDResult['all']))
39         {
40                 $bDidSomething = true;
41                 // TODO: path detection, detection memory, etc.
42
43                 $oDB =& getDB();
44                 passthru('createlang plpgsql nominatim');
45                 pgsqlRunScriptFile(CONST_Path_Postgresql_Contrib.'/_int.sql');
46                 pgsqlRunScriptFile(CONST_Path_Postgresql_Contrib.'/hstore.sql');
47                 pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/postgis.sql');
48                 pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/spatial_ref_sys.sql');
49                 pgsqlRunScriptFile(CONST_BasePath.'/data/country_name.sql');
50                 pgsqlRunScriptFile(CONST_BasePath.'/data/country_osm_grid.sql');
51                 pgsqlRunScriptFile(CONST_BasePath.'/data/gb_postcode.sql');
52                 pgsqlRunScriptFile(CONST_BasePath.'/data/us_statecounty.sql');
53                 pgsqlRunScriptFile(CONST_BasePath.'/data/us_state.sql');
54                 pgsqlRunScriptFile(CONST_BasePath.'/data/worldboundaries.sql');
55         }
56
57         if (isset($aCMDResult['all']) && !isset($aCMDResult['import-data'])) $aCMDResult['import-data'] = $aCMDResult['all'];
58         if (isset($aCMDResult['import-data']) && $aCMDResult['import-data'])
59         {
60                 $bDidSomething = true;
61                 passthru(CONST_BasePath.'/osm2pgsql/osm2pgsql -lsc -O gazetteer -C 10000 --hstore -d nominatim '.$aCMDResult['import-data']);
62         }
63
64         if ($aCMDResult['create-functions'] || isset($aCMDResult['all']))
65         {
66                 $bDidSomething = true;
67                 $sTemplate = file_get_contents(CONST_BasePath.'/sql/functions.sql');
68                 $sTemplate = str_replace('{modulepath}',CONST_BasePath.'/module', $sTemplate);
69                 pgsqlRunScript($sTemplate);
70         }
71
72         if ($aCMDResult['create-tables'] || isset($aCMDResult['all']))
73         {
74                 $bDidSomething = true;
75                 pgsqlRunScriptFile(CONST_BasePath.'/sql/tables.sql');
76
77                 // re-run the functions
78                 $sTemplate = file_get_contents(CONST_BasePath.'/sql/functions.sql');
79                 $sTemplate = str_replace('{modulepath}',CONST_BasePath.'/module', $sTemplate);
80                 pgsqlRunScript($sTemplate);
81         }
82
83         if ($aCMDResult['create-partitions'] || isset($aCMDResult['all']))
84         {
85                 $bDidSomething = true;
86                 $oDB =& getDB();
87                 $sSQL = 'select distinct country_code from country_name order by country_code';
88                 $aPartitions = $oDB->getCol($sSQL);
89                 if (PEAR::isError($aPartitions))
90                 {
91                         fail($aPartitions->getMessage());
92                 }
93                 $aPartitions[] = 'none';
94
95                 $sTemplate = file_get_contents(CONST_BasePath.'/sql/partitions.src.sql');
96                 preg_match_all('#^-- start(.*?)^-- end#ms', $sTemplate, $aMatches, PREG_SET_ORDER);
97                 foreach($aMatches as $aMatch)
98                 {
99                         $sResult = '';
100                         foreach($aPartitions as $sPartitionName)
101                         {
102                                 $sResult .= str_replace('-partition-', $sPartitionName, $aMatch[1]);
103                         }
104                         $sTemplate = str_replace($aMatch[0], $sResult, $sTemplate);
105                 }
106                 pgsqlRunScript($sTemplate);
107         }
108
109         if ($aCMDResult['load-data'] || isset($aCMDResult['all']))
110         {
111                 $bDidSomething = true;
112
113                 $oDB =& getDB();
114                 if (!pg_query($oDB->connection, 'TRUNCATE placex')) fail(pg_last_error($oDB->connection));
115                 echo '.';
116                 if (!pg_query($oDB->connection, 'TRUNCATE place_addressline')) fail(pg_last_error($oDB->connection));
117                 echo '.';
118                 if (!pg_query($oDB->connection, 'TRUNCATE location_area')) fail(pg_last_error($oDB->connection));
119                 echo '.';
120                 if (!pg_query($oDB->connection, 'DROP SEQUENCE seq_place')) fail(pg_last_error($oDB->connection));
121                 echo '.';
122                 if (!pg_query($oDB->connection, 'CREATE SEQUENCE seq_place start 100000')) fail(pg_last_error($oDB->connection));
123                 echo '.';
124
125                 $iInstances = 16;
126                 $aDBInstances = array();
127                 for($i = 0; $i < $iInstances; $i++)
128                 {
129                         $aDBInstances[$i] =& getDB(true);
130                         $sSQL = 'insert into placex (osm_type, osm_id, class, type, name, admin_level, ';
131                         $sSQL .= 'housenumber, street, isin, postcode, country_code, extratags, ';
132                         $sSQL .= 'geometry) select * from place where osm_id % '.$iInstances.' = '.$i;
133                         if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) fail(pg_last_error($oDB->connection));
134                 }
135                 $bAnyBusy = true;
136                 while($bAnyBusy)
137                 {
138                         $bAnyBusy = false;
139                         for($i = 0; $i < $iInstances; $i++)
140                         {
141                                 if (pg_connection_busy($aDBInstances[$i]->connection)) $bAnyBusy = true;
142                         }
143                         sleep(1);
144                         echo '.';
145                 }
146                 echo "\n";
147         }
148
149         if (!$bDidSomething)
150         {
151                 showUsage($aCMDOptions, true);
152         }
153
154         function pgsqlRunScriptFile($sFilename)
155         {
156                 if (!file_exists($sFilename)) fail('unable to find '.$sFilename);
157
158                 // Convert database DSN to psql paramaters
159                 $aDSNInfo = DB::parseDSN(CONST_Database_DSN);
160                 $sCMD = 'psql -f '.$sFilename.' '.$aDSNInfo['database'];
161
162                 $aDescriptors = array(
163                         0 => array('pipe', 'r'),
164                         1 => array('pipe', 'w'),
165                         2 => array('file', '/dev/null', 'a')
166                 );
167                 $ahPipes = null;
168                 $hProcess = proc_open($sCMD, $aDescriptors, $ahPipes);
169                 if (!is_resource($hProcess)) fail('unable to start pgsql');
170
171                 fclose($ahPipes[0]);
172
173                 // TODO: error checking
174                 while(!feof($ahPipes[1]))
175                 {
176                         echo fread($ahPipes[1], 4096);
177                 }
178                 fclose($ahPipes[1]);
179
180                 proc_close($hProcess);
181         }
182
183         function pgsqlRunScript($sScript)
184         {
185                 // Convert database DSN to psql paramaters
186                 $aDSNInfo = DB::parseDSN(CONST_Database_DSN);
187                 $sCMD = 'psql '.$aDSNInfo['database'];
188
189                 $aDescriptors = array(
190                         0 => array('pipe', 'r'),
191                         1 => array('pipe', 'w'),
192                         2 => array('file', '/dev/null', 'a')
193                 );
194                 $ahPipes = null;
195                 $hProcess = proc_open($sCMD, $aDescriptors, $ahPipes);
196                 if (!is_resource($hProcess)) fail('unable to start pgsql');
197
198                 fwrite($ahPipes[0], $sScript);
199                 fclose($ahPipes[0]);
200
201                 // TODO: error checking
202                 while(!feof($ahPipes[1]))
203                 {
204                         echo fread($ahPipes[1], 4096);
205                 }
206                 fclose($ahPipes[1]);
207
208                 proc_close($hProcess);
209         }