ogr2ogrの準備
昨日は、Windows 32bit用のogr2ogr.exeを求めて下記をダウンロード&解凍するところまで行きました。次はコンソールでコマンドを叩く準備をします。
ZIPを解凍すると ↓ こんなフォルダ構造になってて、binをカレントにすればogr2ogrを起動できる模様。コマンドのヘルプを、後々のため載せておきます。
解凍先
┗ bin
┣ gdal111.dll など
┣ …
┗ gdal
┗ apps
┣ ogr2ogr.exe
┗ …
$cd
R:\release-1500-gdal-1-11-1-mapserver-6-4-1\bin
$"gdal/apps/ogr2ogr" --version
GDAL 1.11.1, released 2014/09/24
$"gdal/apps/ogr2ogr" --help
Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
[-select field_list] [-where restricted_where]
[-progress] [-sql ] [-dialect dialect]
[-preserve_fid] [-fid FID]
[-spat xmin ymin xmax ymax] [-geomfield field]
[-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
[-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]
dst_datasource_name src_datasource_name
[-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3|layer_dim] [layer [layer ...]]
Advanced options :
[-gt n]
[-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent]
[-clipsrcsql sql_statement] [-clipsrclayer layer]
[-clipsrcwhere expression]
[-clipdst [xmin ymin xmax ymax]|WKT|datasource]
[-clipdstsql sql_statement] [-clipdstlayer layer]
[-clipdstwhere expression]
[-wrapdateline][-datelineoffset val]
[[-simplify tolerance] | [-segmentize max_dist]]
[-addfields]
[-relaxedFieldNameMatch]
[-fieldTypeToString All|(type1[,type2]*)] [-unsetFieldWidth]
[-fieldmap identity | index1[,index2]*]
[-splitlistfields] [-maxsubfields val]
[-explodecollections] [-zfield field_name]
[-gcp pixel line easting northing [elevation]]* [-order n | -tps]
Note: ogr2ogr --long-usage for full help.
ようやくogr2ogrでインポート
一応ogr2ogrを使えそうなので、まず昨日紹介した下記資料と同じオプションで実行してみます。
$cd
R:\release-1500-gdal-1-11-1-mapserver-6-4-1\bin
$gdal\apps\ogr2ogr -overwrite -progress -f "MySQL"
MYSQL:zcta,user=root R:\zip\tl_2013_us_zcta510.shp
# just one line actually
ERROR 1: MySQL connect failed for: zcta,user=root
Access denied for user 'root'@'localhost' (using password: NO)
ERROR 1: MySQL connect failed for: zcta,user=root
Access denied for user 'root'@'localhost' (using password: NO)
ERROR 1: MySQL connect failed for: zcta,user=root
Access denied for user 'root'@'localhost' (using password: NO)
ERROR 1: MySQL driver doesn't currently support database creation.
Please create database before using.
MySQL driver failed to create MYSQL:zcta,user=root
いきなりエラー。メッセージを見るとユーザ認証の問題らしく、PostGISでも最初はよく嵌まります。PostGISではpsqlの使い方を覚えれば済みますが、今回はogr2ogrからMySQLに接続する場合のパスワード入力方法を調べないと…。ogr2ogrのコマンドリファレンスではなく、下記にありました。
When opening a database, it's name should be specified in the form "MYSQL:dbname[,options]" where the options can include comma seperated items like "user=*userid*", "password=*password*", "host=*host*" and "port=*port*".
先ほどの引数のうち「user-root」の後に「,password=*****」を付ければ良さそう。要するにデータベース接続文字列の中に含めるという。で再度やってみます。ただし先に、インポート先のデータベースを作成。先ほどのエラーメッセージの最後の方にPlease create database before using.とあったので。
mysql> CREATE DATABASE zcta;
Query OK, 1 row affected (0.00 sec)
$cd
R:\release-1500-gdal-1-11-1-mapserver-6-4-1\bin
$gdal\apps\ogr2ogr -overwrite -progress -f "MySQL"
MYSQL:zcta,user=root,password=******** R:\zip\tl_2013_us_zcta510.shp
# just one line actually
やっとできました(´∀`;) 実行すると「0...10...」と進渉が出て(-progressオプションによる)、8分くらいかかって完了。元のシェープファイルが800MBと大きいので所要時間はこんなものかな。
一度投入して、-overwriteオプションなしで再度実行すると「レイヤーが既存」と ↓ エラーになります。レイヤーというのはここではテーブル。overwriteは、ogr2ogrのコマンドリファレンスにDelete the output layer and recreate it emptyとある通り、いったんクリアしてやり直すのに有用。
$gdal\apps\ogr2ogr -progress -f "MySQL"
MYSQL:zcta,user=root,password=******** R:\zip\tl_2013_us_zcta510.shp
# just one line actually
FAILED: Layer tl_2013_us_zcta510 already exists, and -append not specified.
Consider using -append, or -overwrite.
ERROR 1: Terminating translation prematurely after failed
translation of layer tl_2013_us_zcta510 (use -skipfailures to skip errors)
結果の確認は明日します。一つ気になるのは、psqlみたいに「パスワードが必要な時は、文字を表示しない入力プロンプトを出す」ことがogr2ogrでは無理そうなこと。もともとデータベースの接続クライアントではないので当然ですが。上のようにスクリーンショットを撮って人に説明する時、パスワードをいちいちマスクするのは面倒だなぁ。
MySQLとの関係でみると、ogr2ogrは「シェープファイルを解析してMySQL投入用クエリを作る」のと「データベースへ接続しクエリを発行する」を連続して一気に行う。それは便利なんだけど、前者と後者を分離したい時はどうしよう? ogr2ogrのコマンドリファレンスを眺める限り、どうも無理そうな感じ。
PostGISでは前者がshp2pgsql、後者がpsqlと役割分担されているので、間をユーザ自身がSQLファイルかパイプでつなぐ手間がある反面、手順を分離できる利点もあります。例えばインポート用クエリ出力を一回だけ行い、それを複数のDBに繰り返し投入する。インポートエラーが起きた場合、原因をクエリで特定する。psqlから外部コマンドとしてshp2pgsqlを呼び出し、インポートとその後のクエリをシームレスに行なう、等々。
それはさておき、シェープファイルをMySQLの空間データにすることはできたので(多分)、明日以降しばらく試します。記事タイトルを、今日までの「ポータブルに使う」から空間データを使う旨に変えて。