カテゴリー【PostgreSQL、C/C++、Redis】
PostgreSQLでGEOGRAPHY検索をC言語から行う
POSTED BY
2024-10-12
2024-10-12


【Redisメモ・6】GEORADIUS_RO関数をNode.jsから呼ぶ
上記事のPostgreSQL/C言語版です。前回、イオンスタイル入間から最寄りの駅を近い順に検索してみたが、それをC言語から行ってみます。
PostgreSQLクライアント for C言語のインストール
apt install libpq-dev
イオンスタイル入間を中心に半径10km以内の駅を近い順に20個抽出、というPostgreSQL文は以下のように書きます。
SELECT name, ST_X(geom::geometry) AS longitude, ST_Y(geom::geometry) AS latitude, ST_Distance('SRID=4326;POINT(139.394872 35.822019)', geom) AS distance FROM ekipos WHERE ST_DWithin(geom, ST_GeographyFromText('SRID=4326;POINT(139.394872 35.822019)'), 10000.0) ORDER BY distance LIMIT 20
これをC言語で書いて呼んでみます。
| C/C++ | georadius_test_pg.c | GitHub Source |
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <postgresql/libpq-fe.h>
int main(int argc, char **argv) {
PGconn *conn;
PGresult *res;
int i,n;
struct timeval tv_fr,tv_to;
double tm_fr,tm_to;
char sql[2048];
conn = PQconnectdb( "host=127.0.0.1 port=5432 dbname=ekidb" );
if(!conn || PQstatus( conn ) == CONNECTION_BAD ){
fprintf(stderr, "PQconnectdb error\n");
if(conn){
PQfinish(conn);
}
return (-1);
}
sprintf(sql,
"SELECT name, ST_X(geom::geometry) AS longitude, ST_Y(geom::geometry) AS latitude,"
" ST_Distance('SRID=4326;POINT(139.394872 35.822019)', geom) AS distance"
" FROM ekipos WHERE ST_DWithin(geom, ST_GeographyFromText('SRID=4326;POINT(139.394872 35.822019)'), 10000.0)"
" ORDER BY distance LIMIT 20");
fprintf(stdout,"%s\n",sql);
gettimeofday(&tv_fr, NULL);
res = PQexec(conn, sql);
gettimeofday(&tv_to, NULL);
tm_fr = (((double)tv_fr.tv_sec)*((double)1000000)+((double)tv_fr.tv_usec));
tm_to = (((double)tv_to.tv_sec)*((double)1000000)+((double)tv_to.tv_usec));
fprintf(stdout,"fr=%lf,to=%lf,diff=%lf microsec\n",tm_fr,tm_to,tm_to - tm_fr);
fprintf(stdout,"関数実行時間 %lfマイクロ秒\n",tm_to - tm_fr);
n = 0;
if(res){
if( PQresultStatus( res ) != PGRES_TUPLES_OK ){
fprintf(stderr, "PQexec error %s\n",PQresultErrorMessage( res ) );
}
else{
n = PQntuples( res );
}
}
fprintf(stdout, "%d個の駅が該当しました。\n",n);
for( i = 0; i < n; i++ ){
fprintf(stdout, "%d %s(%s %s) %sM\n",i + 1,
PQgetvalue( res,i,0 ),
PQgetvalue( res,i,1 ),
PQgetvalue( res,i,2 ),
PQgetvalue( res,i,3 ) );
}
if(res){
PQclear(res);
}
PQfinish(conn);
return 0;
}
コンパイル
gcc -o georadius_test_pg.x georadius_test_pg.c -lpq
実行結果
./georadius_test_pg.x
SELECT name, ST_X(geom::geometry) AS longitude, ST_Y(geom::geometry) AS latitude, ST_Distance('SRID=4326;POINT(139.394872 35.822019)', geom) AS distance FROM ekipos WHERE ST_DWithin(geom, ST_GeographyFromText('SRID=4326;POINT(139.394872 35.822019)'), 10000.0) ORDER BY distance LIMIT 20
fr=1602502127941979.000000,to=1602502127969246.000000,diff=27267.000000 microsec
関数実行時間 27267.000000マイクロ秒
20個の駅が該当しました。
1 武蔵藤沢-11(139.412736 35.820963) 1618.55278664M
2 入間市-11(139.390294 35.842904) 2353.94189341M
3 狭山ヶ丘-11(139.416975 35.810445) 2374.69603638M
4 稲荷山公園-11(139.39842 35.845112) 2582.28061472M
5 入曽-11(139.427304 35.832481) 3152.08537677M
6 仏子-11(139.360115 35.83769) 3589.75772324M
7 狭山市-11(139.413015 35.856936) 4206.73664685M
8 小手指-11(139.438016 35.800535) 4570.19158489M
9 元加治-11(139.345316 35.84058) 4928.5575168M
10 新所沢-11(139.457069 35.805854) 5900.27449552M
11 西武球場前-11(139.41966 35.77093) 6095.38321915M
12 金子-11(139.328546 35.810822) 6121.42383148M
13 下山口-11(139.441097 35.77941) 6309.44502193M
14 西所沢-11(139.455959 35.789303) 6607.71472248M
15 新狭山-11(139.433499 35.873993) 6740.36207839M
16 航空公園-11(139.465641 35.798272) 6917.51230648M
17 東飯能-11(139.325965 35.852928) 7107.75837244M
18 箱根ケ崎-13(139.346805 35.771158) 7122.20419001M
19 遊園地西-11(139.440166 35.769042) 7163.50373723M
20 西武遊園地-13(139.442747 35.765881) 7584.70286732M
直線距離計算のわずかな違い以外は、Redisのときと全く同じ結果が無事返ってきた…と言いたいところだが、20番目に近い駅の判定が、こちらでは西武遊園地だが、Redisでは飯能だった。25個取得にすると、順番は違えど両方出てきます。
Android
iPhone/iPad
Flutter
MacOS
Windows
Debian
Ubuntu
CentOS
FreeBSD
RaspberryPI
HTML/CSS
C/C++
PHP
Java
JavaScript
Node.js
Swift
Python
MatLab
Amazon/AWS
CORESERVER
Google
仮想通貨
LINE
OpenAI/ChatGPT
IBM Watson
Microsoft Azure
Xcode
VMware
MySQL
PostgreSQL
Redis
Groonga
Git/GitHub
Apache
nginx
Postfix
SendGrid
Hackintosh
Hardware
Fate/Grand Order
ウマ娘
将棋
ドラレコ
※本記事は当サイト管理人の個人的な備忘録です。本記事の参照又は付随ソースコード利用後にいかなる損害が発生しても当サイト及び管理人は一切責任を負いません。
※本記事内容の無断転載を禁じます。
※本記事内容の無断転載を禁じます。
【WEBMASTER/管理人】
自営業プログラマーです。お仕事ください!ご連絡は以下アドレスまでお願いします★
【キーワード検索】
【最近の記事】【全部の記事】
LetsEncrypt/certbotの証明書自動更新がエラーになる場合Wav2Lipのオープンソース版を改造して外部から呼べるAPI化する
Wav2Lipのオープンソース版で静止画の口元のみを動かして喋らせる
【iOS】アプリアイコン・ロゴ画像の作成・設定方法
オープンソースリップシンクエンジンSadTalkerをAPI化してアプリから呼ぶ【2】
オープンソースリップシンクエンジンSadTalkerをAPI化してアプリから呼ぶ【1】
【Xcode】iPhone is not available because it is unpairedの対処法
【Let's Encrypt】Failed authorization procedure 503の対処法
【Debian】古いバージョンでapt updateしたら404 not foundでエラーになる場合
ファイアウォール内部のWindows11 PCにmacOS Sequoiaからリモートデスクトップする
【人気の記事】【全部の記事】
進研ゼミチャレンジタッチをAndroid端末化する【Windows10】リモートデスクトップ間のコピー&ペーストができなくなった場合の対処法
Windows11+WSL2でUbuntuを使う【2】ブリッジ接続+固定IPの設定
【C/C++】小数点以下の切り捨て・切り上げ・四捨五入
GitLabにHTTPS経由でリポジトリをクローン&読み書きを行う
Windows11のコマンドプロンプトでテキストをコピーする
【Apache】サーバーに同時接続可能なクライアント数を調整する
Googleスプレッドシートを編集したら自動で更新日時を入れる
緯度経度の度単位10進数表現とミリ秒表現の相互変換
PostgreSQLをソースコードからインストールしてsystemdのサービスとして動かす
【カテゴリーリンク】
Android
iPhone/iPad
Flutter
MacOS
Windows
Debian
Ubuntu
CentOS
FreeBSD
RaspberryPI
HTML/CSS
C/C++
PHP
Java
JavaScript
Node.js
Swift
Python
MatLab
Amazon/AWS
CORESERVER
Google
仮想通貨
LINE
OpenAI/ChatGPT
IBM Watson
Microsoft Azure
Xcode
VMware
MySQL
PostgreSQL
Redis
Groonga
Git/GitHub
Apache
nginx
Postfix
SendGrid
Hackintosh
Hardware
Fate/Grand Order
ウマ娘
将棋
ドラレコ