raster2pgsql
ラスタローダを使ってPostGISラスタを既存のラスタファイルからロードするのは、最もよく行われます。
raster2pgsql
は、GDALがサポートするラスタ書式をPostGISラスタテーブルにロードするのに適切なSQLにする実行ファイルです。ラスタのオーバビューの生成だけでなく、ラスタファイルのフォルダのロードも可能です。
かなり多くの場合、(ご自分のGDALライブラリをコンパイルしない限り) raster2pgsqlはPostGISの一部としてコンパイルされるので、実行ファイルがサポートするラスタタイプはGDALの依存ライブラリでコンパイルされたものと同じになります。お手持ちのraster2pgsql
がサポートするラスタタイプの一覧は、-G
スイッチで見ることができます。
同じアラインメントを持つラスタの集合から特定の要素のオーバビューを生成する時、オーバビューが同じアラインメントを持たないことがあります。オーバビューが同じアラインメントを持たない例についてはhttp://trac.osgeo.org/postgis/ticket/1764をご覧下さい。 |
ローダを用いて入力ファイルを100x100のタイルで生成して、データベースにアップロードする例は、次の通りです。
# -s use srid 4326 # -I create spatial index # -C use standard raster constraints # -M vacuum analyze after load # *.tif load all these files # -F include a filename column in the raster table # -t tile the output 100x100 # public.demelevation load into this table raster2pgsql -s 4326 -I -C -M -F -t 100x100 *.tif public.demelevation > elev.sql # -d connect to this database # -f read this file after connecting psql -d gisdb -f elev.sql
対象テーブル名の一部としてスキーマを指定しない場合には、テーブルはデータベースのデフォルトスキーマ内かユーザが接続しているスキーマ内に作られます。 |
変換とアップロードはUNIXのパイプを使うと一回で実行できます。
raster2pgsql -s 4326 -I -C -M *.tif -F -t 100x100 public.demelevation | psql -d gisdb
マサチューセッツ州平面のメートル単位の空中写真タイルをaerial
という名前のスキーマにロードします。 元の画像と2, 4レベルのオーバビューのテーブルとを生成します。 データ格納にCOPYを使用し (データベースに仲介ファイルなくまっすぐ入ります)、-eでトランザクションを指定しないようにします (待たずにテーブルのデータを見たい場合には良いです)。ラスタを128x128ピクセルのタイルに分解してラスタ制約を適用します。INSERTモードでなくCOPYモードを使用します。-Fで、カラム名をタイル切り出し元ファイルのファイル名にします。
raster2pgsql -I -C -e -Y -F -s 26986 -t 128x128 -l 2,4 bostonaerials2008/*.jpg aerials.boston | psql -U postgres -d gisdb -h localhost -p 5432
--get a list of raster types supported: raster2pgsql -G
-Gコマンドの出力は次のようになります
Available GDAL raster formats: Virtual Raster GeoTIFF National Imagery Transmission Format Raster Product Format TOC format ECRG TOC format Erdas Imagine Images (.img) CEOS SAR Image CEOS Image ... Arc/Info Export E00 GRID ZMap Plus Grid NOAA NGS Geoid Height Grids
-?
ヘルプを表示します。引数を全く指定しない場合にも表示されます。
-G
サポートされているラスタ書式を印字します。
-c
新しいテーブルを生成し、ラスタを入れます。これがデフォルトモードです。
-a
既存のテーブルにラスタを追加します。
-d
テーブルを削除し、新しいテーブルを生成し、ラスタを入れます。
-p
準備モード、テーブルを作るだけです。
-C
SRIDやピクセルサイズ等のラスタ制約を適用して、raster_columns
ビューで適切な登録ができるようにします。
-x
制約の最大範囲を無効にします。-Cフラグが使われている場合のみ適用されます。
-r
正規ブロック制約 (空間的に一意で網羅タイル)を適用します。-Cフラグが使用されている場合のみ適用されます。
-s <SRID>
出力ラスタを指定されたSRIDにします。 指定しないか0を指定した場合、ラスタのメタデータに対して、適切なSRIDを決定するためのチェックを行います。
-b BAND
ラスタから抽出するバンドのインデクス (1始まり)。1より多いバンドを抽出するには、コンマ(,)で区切ります。指定しない場合、全てのバンドが抽出されます。
-t TILE_SIZE
行毎に挿入するラスタを切断します。TILE_SIZE
は、「幅x高さ」で表現しますが、"auto"を指定すると、最初のラスタを使って適切なタイルサイズが計算され、全てのラスタに適用されます。
-P
全てのタイルが同じ幅と高さを持つことを保証するために、右端、下端のタイルに詰め物を施します。
-R, --register
ファイルシステム (データベース外)ラスタとして、ラスタを登録します。
データベースには、ラスタのメタデータとラスタのファイルパスのみ格納されます (ピクセルは格納されません)。
-l OVERVIEW_FACTOR
ラスタのオーバビューを生成します。一つより多い係数を用いる場合は、コンマ (,) で区切ります。オーバビューのテーブル名はo_overview factor
_table
となります。overview factor
にはオーバビュー係数が入り、table
には基底テーブル名が入ります。生成されるオーバビューはデータベースに格納され、-Rは無視されます。生成されたSQLファイルは元データのテーブルとオーバビューテーブルの両方を含むことに注意して下さい。
-N NODATA
NODATA値を持たないバンドで使用するNODATA値を設定します。
-f COLUMN
出力先ラスタカラムの名前を指定します。デフォルトは'rast'です。
-F
ファイル名でカラムを追加します。
-n COLUMN
ファイル名カラムの名前を指定します。-Fを暗に含みます。
-q
PostgreSQL識別子に引用符を付けます。
-I
ラスタカラムにGiSTインデクスを生成します。
-M
ラスタテーブルにvacuum analyzeを行います。
-k
空タイルを保持してラスタバンドごとのNODATA値のチェックを省きます。チェック時間を抑えることになりますが、データベース内の不要な行がずっと増えて、これらの行が空タイルとされないことに注意して下さい。
-T tablespace
生成されるテーブルのテーブルスペースを指定します。-Xフラグを併用しない場合には、インデクス (主キーを含む)はデフォルトのテーブルスペースを使用することにご注意ください。
-X tablespace
テーブルの新しいインデクスに使うテーブル空間を指定します。主キーに適用され、-Iフラグがある場合においては空間インデクスにも適用されます。
-Y max_rows_per_copy=50
COPYステートメントを使い、INSERTを使いません。任意でmax_rows_per_copy
を指定します。指定しない場合のデフォルト値は50です。
-e
ステートメント毎に実行して、トランザクションを使用しないようにします。
-E ENDIAN
生成されるラスタのバイナリ出力のエンディアンを制御します。XDR (訳注: ビッグエンディアン)の場合は0を、NDR (訳注:リトルエンディアン)の場合は1を、それぞれ指定します。デフォルトは1です。現時点ではNDR出力のみサポートします。
-V version
出力書式の版を指定します。デフォルトは0です。現時点では0のみサポートします。
データベース内でラスタやラスタテーブルを生成したい場合が多くあります。これを行うための関数が多数あります。一般的な手順は次の通りです。
新しいラスタ行を保持するためのラスタカラムを持つテーブルを生成します:
CREATE TABLE myrasters(rid serial primary key, rast raster);
この目標で助けとなる関数は多数あります。他のラスタの派生でないラスタを生成する場合、ST_MakeEmptyRasterとST_AddBandを順次実行して作業を開始します
ジオメトリからラスタを生成することもできます。ST_AsRasterを使います。ST_UnionやST_MapAlgebraFctや、地図解析関数群等といった、他の関数を組み合わせる場合もあります。
既存テーブルから新しいラスタテーブルを生成するための多数の選択肢があります。たとえば、ST_Transformを使って、既存テーブルから異なる投影法のラスタテーブルを生成します
はじめにテーブルにデータを入れたら、ラスタカラムに空間インデクスを生成したくなるでしょう:
CREATE INDEX myrasters_rast_st_convexhull_idx ON myrasters USING gist( ST_ConvexHull(rast) );
ST_ConvexHullを使用していることに注意して下さい。多くのラスタ演算子はラスタの凸包を元にしています。
2.0より前の PostGIS ラスタは、エンベロープを基本にして、凸包ではありませんでした。空間インデクスを適切に働かせるには、エンベロープを基本にしたインデクスを削除して、凸包を元にしたインデクスに置き換えます。 |
AddRasterConstraintsを用いてラスタ制約を適用します
raster2pgsql
ツールはGDALを使用してラスタデータにアクセスします。また、クラウドの「オブジェクト保存」 (AWS S3やGoogle Cloud Storage等)にリモート格納されたラスタを読む能力という、重要なGDAL機能の利点を享受することができます。
クラウドストレージの効率的な仕様には、「クラウド最適化」された書式の使用が必要です。最も知られて幅広く使われているものは、 "cloud optimized GeoTIFF"です。JPEGや非タイル化TIFFなどの非クラウド書式を使うと、発揮される能力は非常に貧弱になります。システムがラスタの一部分にアクセスする必要に迫られるたびに全体をダウンロードするためです。
まず、ラスタをあなたが選択したクラウドストレージに保存します。保存したら、アクセスに使うURIが得られます。"http"URIか、時々特別なサービスを示すURI ( "s3://bucket/object"等)です。非公開バケットにアクセスするには、接続認証のためのGDALコンフィギュレーションオプションが必要になります。このコマンドはクラウドラスタから読み、データベースに書きます。
AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx \ AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ raster2pgsql \ -s 990000 \ -t 256x256 \ -I \ -R \ /vsis3/your.bucket.com/your_file.tif \ your_table \ | psql your_db
テーブルがロードされたら、データベースにリモートラスタらか読むためのアクセス許可を与えます。postgis.enable_outdb_rastersとpostgis.gdal_enabled_driversの、二つのアクセス許可を設定します。
SET postgis.enable_outdb_rasters = true; SET postgis.gdal_enabled_drivers TO 'ENABLE_ALL';
確実に変更するには、データベースに直接設定します。新しい設定を使うには再接続が必要です。
ALTER DATABASE your_db SET postgis.enable_outdb_rasters = true; ALTER DATABASE your_db SET postgis.gdal_enabled_drivers TO 'ENABLE_ALL';
非公開ラスタの場合、クラウドラスタから読み取るアクセスキーを与えなければならない場合があります。raster2pgsql
の書き込みに使用したのと同じキーを、データベース内でpostgis.gdal_vsi_options設定と共に使用するように設定できます。key=value
ペアをスペースで区切ることで、複数のオプションを設定できることに注意してください。
SET postgis.gdal_vsi_options = 'AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
データをロードし、パーミッションが設定されると、ラスタテーブルは他のラスタテーブルとおなじように、同じ関数を使って、対話的処理が可能となります。データベースは、ピクセルデータの読み取りが必要なら、クラウドへの接続の全てを扱います。
PostGISが生成する、二つのラスタカタログのビューがあります。両方ともラスタテーブルの制約の中に埋め込まれる情報を用いています。結果として、カタログビューは、テーブル内のラスタデータに制約が働くため、常にラスタデータとの矛盾がありません。
raster_columns
ラスタタイプのデータベースにおける全てのラスタテーブルカラムのカタログです。
raster_overviews
データベース内の、より詳細なテーブルのためのオーバビューを提供するラスタテーブルのカラム全てのカタログです。この種のテーブルは、ロード時に-l
を指定した時に生成されます。
raster_columns
は、ラスタタイプのデータベースにおける全てのラスタテーブルカラムのカタログです。テーブルの制約を使ったビューなので、他のデータベースのバックアップからラスタテーブルをリストアしたとしても、情報は常に矛盾がありません。raster_columns
カタログには次のカラムがあります。
ローダを使わずにテーブルを生成したり、ロード時に-C
フラグを忘れたりした場合には、事後にAddRasterConstraintsで制約を強制でき、raster_columns
カタログは、ラスタタイルの共通の情報を登録します。
r_table_catalog
テーブルが存在するデータベースです。これは常に現在のデータベースを読みます。
r_table_schema
ラスタテーブルが属するデータベーススキーマです。
r_table_name
ラスタテーブルです。
r_raster_column
ラスタタイプであるr_table_name
テーブルのカラムです。PostGISには、一つのテーブルに複数のラスタカラムを持つことを妨げません。異なるラスタカラムを持つラスタテーブルが、ラスタカラム毎に複数回出現するテーブルを持つことができます。
srid
ラスタの空間参照系識別番号です。Section 4.5, “空間参照系”にあるエントリであるべきです。
scale_x
地理空間座標とピクセルの間の拡大縮小係数です。これは、ラスタカラムのすべてのタイルが同じscale_x
を持ち、制約が適用されている場合のみ出現します。詳細情報についてはST_ScaleXを参照してください。
scale_y
地理空間座標とピクセルの間の拡大縮小係数です。これは、ラスタカラムのすべてのタイルが同じscale_y
を持ち、scale_y
の制約が適用されている場合のみ出現します。詳細情報についてはST_ScaleYを参照してください。
blocksize_x
ラスタタイルごとの幅 (横方向のピクセル数)です。詳細情報についてはST_Widthを参照してください。
blocksize_y
ラスタタイルごとの高さ (縦方向のピクセル数)です。詳細情報についてはST_Heightを参照してください。
same_alignment
全てのラスタタイルが同じアラインメントを持っているかを示す真偽値です。詳細情報についてはST_SameAlignmentを参照してください。
regular_blocking
ラスタカラムが空間的に一意かつカバレッジタイルの制約を持つなら、TRUEとなります。その他の場合はFALSEになります。。
num_bands
ラスタ集合のタイルごとのバンド数。これと同じ情報が得られる関数は ST_NumBands
pixel_types
バンドごとのピクセルタイプを定義する配列です。この配列の要素数はバンド数と同じです。pixel_typesは、ST_BandPixelTypeで定義されるピクセルタイプの一つを取ります。
nodata_values
バンド毎のnodata_value
を示す倍精度浮動小数点数の配列です。バンド数と同じ配列数となります。これらの値は、バンド毎のほとんどの処理で無視されるべきピクセル値の定義です。これはST_BandNoDataValueで得られる情報と似ています。
out_db
ラスタバンドデータがデータベース外で維持されているかを示す真偽値の配列です。この配列の添え字はバンド番号と同じです。
extent
ラスタ集合における全てのラスタ行の範囲です。集合の範囲を変更するデータを別途ロードする予定である場合、ロード前にDropRasterConstraints関数を実行して、ロード後にAddRasterConstraintsで制約を再適用します。
spatial_index
空間インデクスを持っているかどうかを示す真偽値です。
raster_overviews
は、オーバビューで使われるラスタテーブルカラムに関する情報のカタログで、オーバビューを用いる際に知っておくと便利な情報も持ちます。オーバビューテーブルはraster_columns
とraster_overviews
の両方のカタログに入れられます。オーバビューもラスタの一つであるのは確かですが、より高い解像度テーブルの解像度を落としたカリカチュアになるという特殊な目的を満たすためでもあるからです。ラスタをロードする際に-l
スイッチを使うと、オーバビューが主ラスタテーブルと一緒に生成されます。もしくは、AddOverviewConstraintsを使うと手動で生成できます。
オーバビューテーブルには、他のラスタテーブルと同じ制約と、オーバビュー特有の制約となる追加情報があります。
|
オーバビューの主たる理由は次の二つです。
ズームアウトした際の地図表示を早くするために、元のテーブルの低解像度表現が一般的に使われます。
レコード数が少なく、ピクセル毎の適用範囲が広いため、高解像度の元テーブルより計算が一般的に早くなります。計算は高解像度テーブルより精度は落ちますが、大まかな計算には十分でありえます。
raster_overviews
カタログには、次の情報のカラムがあります。
o_table_catalog
オーバビューテーブルが存在するデータベースです。常に現在のデータベースを読みます。
o_table_schema
オーバビューラスタテーブルが属するデータベーススキーマです。
o_table_name
ラスタオーバビューテーブル名です。
o_raster_column
オーバビューテーブル内のラスタカラムです。
r_table_catalog
このオーバビューの元となるラスタテーブルのデータベースです。常に現在のデータベースを読みます。
r_table_schema
このオーバビューの元となるラスタテーブルが属するデータベーススキーマです。
r_table_name
このオーバビューの元となるラスタテーブルです。
r_raster_column
このオーバビューの元となるラスタカラムです。
overview_factor
- オーバビューテーブルのピラミッドレベルです。高い数字ほど解像度が低くなります。raster2pgsqlは、画像のフォルダを渡された場合は、分割して、イメージファイルのオーバビューの計算とロードを行います。レベル1は元ファイルと同じです。レベル2は、元ファイルの4分の1になります。たとえば、5000x5000ピクセルの画像ファイルのフォルダがあるとして、125x125に分ける場合、画像ファイルごとに(5000*5000)/(125*125) = 1600行のレコードを持ち、o_2
テーブル (レベル2)はceiling(1600/Power(2,2)) = 400行、o_3
(レベル3)ではceiling(1600/Power(2,3) ) = 200行のレコードを持ちます。ピクセルがタイルサイズで割り切れない場合、スクラップタイル (完全には値が入っていない)が得られます。raster2pgsqlによって生成される個々のオーバビュータイルは、元となるラスタと同じピクセル数を持ち、個々のピクセルの表現範囲 (オリジナルの Power(2,overview_factor)ピクセル分)が低い解像度になっている点に注意して下さい。
PostGISラスタに知られている画像書式でラスタをレンダリングするためのSQL関数があります。このことから多数のレンダリングの選択肢が使えます。たとえば、OpenOffice/LibreOfficeを使ってレンダリングが可能で、Rendering PostGIS Raster graphics with LibreOffice Base Reportsにデモンストレーションがあります。さらに、本節で示す通り、多種多様な言語を使用できます。
本節では、PHPのPostgreSQLドライバとST_AsGDALRaster等の関数を使って、HTML imgタグに埋め込むことができるPHPリクエストストリームにラスタの1、2、3バンドを出力する方法を示します。
サンプルクエリでは、 指定したWGS84バウンディングボックスにインタセクトするタイルを取って、 ST_Unionでインタセクトしたタイルを結合して全てのバンドを返し、ST_Transformでユーザ指定投影法に変換し、ST_AsPNGを使ってPNGで結果を出力するためのラスタ関数群全体をまとめる方法を示します。
次で示すスクリプトは、
http://mywebserver/test_raster.php?srid=2249
で、マサチューセッツ州平面 (フィート単位)のラスタ画像を取得するものです。
<?php /** contents of test_raster.php **/ $conn_str ='dbname=mydb host=localhost port=5432 user=myuser password=mypwd'; $dbconn = pg_connect($conn_str); header('Content-Type: image/png'); /**If a particular projection was requested use it otherwise use mass state plane meters **/ if (!empty( $_REQUEST['srid'] ) && is_numeric( $_REQUEST['srid']) ){ $input_srid = intval($_REQUEST['srid']); } else { $input_srid = 26986; } /** The set bytea_output may be needed for PostgreSQL 9.0+, but not for 8.4 **/ $sql = "set bytea_output='escape'; SELECT ST_AsPNG(ST_Transform( ST_AddBand(ST_Union(rast,1), ARRAY[ST_Union(rast,2),ST_Union(rast,3)]) ,$input_srid) ) As new_rast FROM aerials.boston WHERE ST_Intersects(rast, ST_Transform(ST_MakeEnvelope(-71.1217, 42.227, -71.1210, 42.218,4326),26986) )"; $result = pg_query($sql); $row = pg_fetch_row($result); pg_free_result($result); if ($row === false) return; echo pg_unescape_bytea($row[0]); ?>
本節では、Npgsql PostgreSQL .NETドライバとST_AsGDALRaster等の関数を使って、HTML imgタグに埋め込むことができるように、ラスタの1、2、3バンドを出力する方法を示します。
この例ではNpgsql .NET PostgreSQLドライバが必要です。最新版はhttp://npgsql.projects.postgresql.org/にあります。最新版をダウンロードして、ASP.NET の binフォルダに入れるだけでうまくいきます。
サンプルクエリでは、 指定したWGS84バウンディングボックスにインタセクトするタイルを取って、 ST_Unionでインタセクトしたタイルを結合して全てのバンドを返し、ST_Transformでユーザ指定投影法に変換し、ST_AsPNGを使ってPNGで結果を出力するためのラスタ関数群全体をまとめる方法を示します。
この例はC#で実装している点を除いてはSection 10.3.1, “ST_AsPNG を他の関数とあわせて使った PHP 出力例”と同じです。
次で示すスクリプトは、
http://mywebserver/TestRaster.ashx?srid=2249
で、マサチューセッツ州平面 (フィート単位)のラスタ画像を取得します。
-- web.config connection string section -- <connectionStrings> <add name="DSN" connectionString="server=localhost;database=mydb;Port=5432;User Id=myuser;password=mypwd"/> </connectionStrings>
// Code for TestRaster.ashx <%@ WebHandler Language="C#" Class="TestRaster" %> using System; using System.Data; using System.Web; using Npgsql; public class TestRaster : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "image/png"; context.Response.BinaryWrite(GetResults(context)); } public bool IsReusable { get { return false; } } public byte[] GetResults(HttpContext context) { byte[] result = null; NpgsqlCommand command; string sql = null; int input_srid = 26986; try { using (NpgsqlConnection conn = new NpgsqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DSN"].ConnectionString)) { conn.Open(); if (context.Request["srid"] != null) { input_srid = Convert.ToInt32(context.Request["srid"]); } sql = @"SELECT ST_AsPNG( ST_Transform( ST_AddBand( ST_Union(rast,1), ARRAY[ST_Union(rast,2),ST_Union(rast,3)]) ,:input_srid) ) As new_rast FROM aerials.boston WHERE ST_Intersects(rast, ST_Transform(ST_MakeEnvelope(-71.1217, 42.227, -71.1210, 42.218,4326),26986) )"; command = new NpgsqlCommand(sql, conn); command.Parameters.Add(new NpgsqlParameter("input_srid", input_srid)); result = (byte[]) command.ExecuteScalar(); conn.Close(); } } catch (Exception ex) { result = null; context.Response.Write(ex.Message.Trim()); } return result; } }
これは、一つの画像を返すクエリを取り、指定したファイルに出力する、簡単なJavaコンソールアプリケーションです。
最新のPostgreSQL JDBCドライバはhttp://jdbc.postgresql.org/download.htmlからダウンロードできます。
あとで示すコードをコンパイルします。コマンドは次の通りです。
set env CLASSPATH .:..\postgresql-9.0-801.jdbc4.jar javac SaveQueryImage.java jar cfm SaveQueryImage.jar Manifest.txt *.class
次のようにコマンドラインから呼び出します。
java -jar SaveQueryImage.jar "SELECT ST_AsPNG(ST_AsRaster(ST_Buffer(ST_Point(1,5),10, 'quad_segs=2'),150, 150, '8BUI',100));" "test.png"
-- Manifest.txt -- Class-Path: postgresql-9.0-801.jdbc4.jar Main-Class: SaveQueryImage
// Code for SaveQueryImage.java import java.sql.Connection; import java.sql.SQLException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.io.*; public class SaveQueryImage { public static void main(String[] argv) { System.out.println("Checking if Driver is registered with DriverManager."); try { //java.sql.DriverManager.registerDriver (new org.postgresql.Driver()); Class.forName("org.postgresql.Driver"); } catch (ClassNotFoundException cnfe) { System.out.println("Couldn't find the driver!"); cnfe.printStackTrace(); System.exit(1); } Connection conn = null; try { conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/mydb","myuser", "mypwd"); conn.setAutoCommit(false); PreparedStatement sGetImg = conn.prepareStatement(argv[0]); ResultSet rs = sGetImg.executeQuery(); FileOutputStream fout; try { rs.next(); /** Output to file name requested by user **/ fout = new FileOutputStream(new File(argv[1]) ); fout.write(rs.getBytes(1)); fout.close(); } catch(Exception e) { System.out.println("Can't create file"); e.printStackTrace(); } rs.close(); sGetImg.close(); conn.close(); } catch (SQLException se) { System.out.println("Couldn't connect: print out a stack trace and exit."); se.printStackTrace(); System.exit(1); } } }
これは、サーバディレクトリ内でレコードごとにファイルを生成するPythonストアド関数です。plpythonが必要です。plpythonuとplpython3uの両方が正しく動作します。
CREATE OR REPLACE FUNCTION write_file (param_bytes bytea, param_filepath text) RETURNS text AS $$ f = open(param_filepath, 'wb+') f.write(param_bytes) return param_filepath $$ LANGUAGE plpythonu;
--write out 5 images to the PostgreSQL server in varying sizes -- note the postgresql daemon account needs to have write access to folder -- this echos back the file names created; SELECT write_file(ST_AsPNG( ST_AsRaster(ST_Buffer(ST_Point(1,5),j*5, 'quad_segs=2'),150*j, 150*j, '8BUI',100)), 'C:/temp/slices'|| j || '.png') FROM generate_series(1,5) As j; write_file --------------------- C:/temp/slices1.png C:/temp/slices2.png C:/temp/slices3.png C:/temp/slices4.png C:/temp/slices5.png
PSQLから組み込み機能を用いてバイナリを出力するのは簡単ではありません。ここで紹介する方法は、レガシーなラージオブジェクトをサポートするPostgreSQL上に乗っかる、ちょっとしたハックです。まずは、psqlを起動して、データベースに接続します。
この方法はPythonの場合と違い、ローカル機にファイルが生成されます。
SELECT oid, lowrite(lo_open(oid, 131072), png) As num_bytes FROM ( VALUES (lo_create(0), ST_AsPNG( (SELECT rast FROM aerials.boston WHERE rid=1) ) ) ) As v(oid,png); -- you'll get an output something like -- oid | num_bytes ---------+----------- 2630819 | 74860 -- next note the oid and do this replacing the c:/test.png to file path location -- on your local computer \lo_export 2630819 'C:/temp/aerial_samp.png' -- this deletes the file from large object storage on db SELECT lo_unlink(2630819);