prestogres 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +20 -0
- data/LICENSE +202 -0
- data/NOTICE +22 -0
- data/README.md +217 -0
- data/Rakefile +13 -0
- data/VERSION +1 -0
- data/bin/prestogres +254 -0
- data/config/pcp.conf.sample +28 -0
- data/config/pgpool.conf +678 -0
- data/config/pool_hba.conf +84 -0
- data/config/pool_passwd +0 -0
- data/config/postgresql.conf +2 -0
- data/ext/.gitignore +6 -0
- data/ext/depend +26 -0
- data/ext/extconf.rb +4 -0
- data/ext/prestogres_config.c +12 -0
- data/pgpool2/.gitignore +36 -0
- data/pgpool2/AUTHORS +4 -0
- data/pgpool2/COPYING +12 -0
- data/pgpool2/ChangeLog +1 -0
- data/pgpool2/INSTALL +1 -0
- data/pgpool2/Makefile.am +159 -0
- data/pgpool2/Makefile.in +1187 -0
- data/pgpool2/NEWS +4960 -0
- data/pgpool2/README +1 -0
- data/pgpool2/README.euc_jp +1 -0
- data/pgpool2/README.online-recovery +62 -0
- data/pgpool2/TODO +103 -0
- data/pgpool2/ac_func_accept_argtypes.m4 +85 -0
- data/pgpool2/aclocal.m4 +1088 -0
- data/pgpool2/c-compiler.m4 +134 -0
- data/pgpool2/c-library.m4 +325 -0
- data/pgpool2/child.c +2097 -0
- data/pgpool2/config.guess +1532 -0
- data/pgpool2/config.h.in +332 -0
- data/pgpool2/config.sub +1640 -0
- data/pgpool2/configure +15752 -0
- data/pgpool2/configure.in +392 -0
- data/pgpool2/depcomp +522 -0
- data/pgpool2/doc/basebackup.sh +17 -0
- data/pgpool2/doc/pgpool-de.html +4220 -0
- data/pgpool2/doc/pgpool-en.html +5738 -0
- data/pgpool2/doc/pgpool-fr.html +4118 -0
- data/pgpool2/doc/pgpool-ja.css +198 -0
- data/pgpool2/doc/pgpool-ja.html +11279 -0
- data/pgpool2/doc/pgpool-zh_cn.html +4445 -0
- data/pgpool2/doc/pgpool.css +280 -0
- data/pgpool2/doc/pgpool_remote_start +13 -0
- data/pgpool2/doc/recovery.conf.sample +117 -0
- data/pgpool2/doc/tutorial-en.html +707 -0
- data/pgpool2/doc/tutorial-ja.html +422 -0
- data/pgpool2/doc/tutorial-memqcache-en.html +325 -0
- data/pgpool2/doc/tutorial-memqcache-ja.html +370 -0
- data/pgpool2/doc/tutorial-memqcache-zh_cn.html +322 -0
- data/pgpool2/doc/tutorial-watchdog-en.html +306 -0
- data/pgpool2/doc/tutorial-watchdog-ja.html +343 -0
- data/pgpool2/doc/tutorial-watchdog-zh_cn.html +301 -0
- data/pgpool2/doc/tutorial-zh_cn.html +537 -0
- data/pgpool2/doc/watchdog.png +0 -0
- data/pgpool2/doc/wd-en.html +236 -0
- data/pgpool2/doc/wd-en.jpg +0 -0
- data/pgpool2/doc/wd-ja.html +219 -0
- data/pgpool2/doc/wd-ja.jpg +0 -0
- data/pgpool2/doc/wd-zh_cn.html +201 -0
- data/pgpool2/doc/where_to_send_queries.odg +0 -0
- data/pgpool2/doc/where_to_send_queries.pdf +0 -0
- data/pgpool2/general.m4 +166 -0
- data/pgpool2/getopt_long.c +200 -0
- data/pgpool2/getopt_long.h +44 -0
- data/pgpool2/install-sh +251 -0
- data/pgpool2/ltmain.sh +8406 -0
- data/pgpool2/m4/libtool.m4 +7360 -0
- data/pgpool2/m4/ltoptions.m4 +368 -0
- data/pgpool2/m4/ltsugar.m4 +123 -0
- data/pgpool2/m4/ltversion.m4 +23 -0
- data/pgpool2/m4/lt~obsolete.m4 +92 -0
- data/pgpool2/main.c +2971 -0
- data/pgpool2/md5.c +444 -0
- data/pgpool2/md5.h +28 -0
- data/pgpool2/missing +360 -0
- data/pgpool2/mkinstalldirs +40 -0
- data/pgpool2/parser/Makefile.am +50 -0
- data/pgpool2/parser/Makefile.in +559 -0
- data/pgpool2/parser/copyfuncs.c +3310 -0
- data/pgpool2/parser/gram.c +39100 -0
- data/pgpool2/parser/gram.h +940 -0
- data/pgpool2/parser/gram.y +13408 -0
- data/pgpool2/parser/gramparse.h +74 -0
- data/pgpool2/parser/keywords.c +32 -0
- data/pgpool2/parser/keywords.h +39 -0
- data/pgpool2/parser/kwlist.h +425 -0
- data/pgpool2/parser/kwlookup.c +88 -0
- data/pgpool2/parser/list.c +1156 -0
- data/pgpool2/parser/makefuncs.c +518 -0
- data/pgpool2/parser/makefuncs.h +83 -0
- data/pgpool2/parser/memnodes.h +79 -0
- data/pgpool2/parser/nodes.c +29 -0
- data/pgpool2/parser/nodes.h +609 -0
- data/pgpool2/parser/outfuncs.c +5790 -0
- data/pgpool2/parser/parsenodes.h +2615 -0
- data/pgpool2/parser/parser.c +262 -0
- data/pgpool2/parser/parser.h +46 -0
- data/pgpool2/parser/pg_class.h +158 -0
- data/pgpool2/parser/pg_config_manual.h +273 -0
- data/pgpool2/parser/pg_list.h +352 -0
- data/pgpool2/parser/pg_trigger.h +147 -0
- data/pgpool2/parser/pg_wchar.h +492 -0
- data/pgpool2/parser/pool_memory.c +342 -0
- data/pgpool2/parser/pool_memory.h +77 -0
- data/pgpool2/parser/pool_parser.h +222 -0
- data/pgpool2/parser/pool_string.c +121 -0
- data/pgpool2/parser/pool_string.h +37 -0
- data/pgpool2/parser/primnodes.h +1280 -0
- data/pgpool2/parser/scan.c +4094 -0
- data/pgpool2/parser/scan.l +1451 -0
- data/pgpool2/parser/scanner.h +120 -0
- data/pgpool2/parser/scansup.c +221 -0
- data/pgpool2/parser/scansup.h +28 -0
- data/pgpool2/parser/snprintf.c +1102 -0
- data/pgpool2/parser/stringinfo.c +294 -0
- data/pgpool2/parser/stringinfo.h +178 -0
- data/pgpool2/parser/value.c +78 -0
- data/pgpool2/parser/value.h +62 -0
- data/pgpool2/parser/wchar.c +2048 -0
- data/pgpool2/pcp.conf.sample +28 -0
- data/pgpool2/pcp/Makefile.am +40 -0
- data/pgpool2/pcp/Makefile.in +771 -0
- data/pgpool2/pcp/libpcp_ext.h +250 -0
- data/pgpool2/pcp/md5.c +444 -0
- data/pgpool2/pcp/md5.h +28 -0
- data/pgpool2/pcp/pcp.c +1652 -0
- data/pgpool2/pcp/pcp.h +61 -0
- data/pgpool2/pcp/pcp_attach_node.c +172 -0
- data/pgpool2/pcp/pcp_detach_node.c +185 -0
- data/pgpool2/pcp/pcp_error.c +87 -0
- data/pgpool2/pcp/pcp_node_count.c +160 -0
- data/pgpool2/pcp/pcp_node_info.c +198 -0
- data/pgpool2/pcp/pcp_pool_status.c +166 -0
- data/pgpool2/pcp/pcp_proc_count.c +166 -0
- data/pgpool2/pcp/pcp_proc_info.c +261 -0
- data/pgpool2/pcp/pcp_promote_node.c +185 -0
- data/pgpool2/pcp/pcp_recovery_node.c +172 -0
- data/pgpool2/pcp/pcp_stop_pgpool.c +179 -0
- data/pgpool2/pcp/pcp_stream.c +385 -0
- data/pgpool2/pcp/pcp_stream.h +52 -0
- data/pgpool2/pcp/pcp_systemdb_info.c +194 -0
- data/pgpool2/pcp/pcp_watchdog_info.c +211 -0
- data/pgpool2/pcp_child.c +1493 -0
- data/pgpool2/pg_md5.c +305 -0
- data/pgpool2/pgpool.8.in +121 -0
- data/pgpool2/pgpool.conf +553 -0
- data/pgpool2/pgpool.conf.sample +666 -0
- data/pgpool2/pgpool.conf.sample-master-slave +665 -0
- data/pgpool2/pgpool.conf.sample-replication +664 -0
- data/pgpool2/pgpool.conf.sample-stream +664 -0
- data/pgpool2/pgpool.spec +264 -0
- data/pgpool2/pgpool_adm/TODO +7 -0
- data/pgpool2/pgpool_adm/pgpool_adm--1.0.sql +85 -0
- data/pgpool2/pgpool_adm/pgpool_adm.c +558 -0
- data/pgpool2/pgpool_adm/pgpool_adm.control +5 -0
- data/pgpool2/pgpool_adm/pgpool_adm.h +46 -0
- data/pgpool2/pgpool_adm/pgpool_adm.sql.in +85 -0
- data/pgpool2/pool.h +655 -0
- data/pgpool2/pool_auth.c +1390 -0
- data/pgpool2/pool_config.c +5007 -0
- data/pgpool2/pool_config.h +284 -0
- data/pgpool2/pool_config.l +3281 -0
- data/pgpool2/pool_config_md5.c +29 -0
- data/pgpool2/pool_connection_pool.c +812 -0
- data/pgpool2/pool_error.c +242 -0
- data/pgpool2/pool_globals.c +27 -0
- data/pgpool2/pool_hba.c +1723 -0
- data/pgpool2/pool_hba.conf.sample +67 -0
- data/pgpool2/pool_ip.c +567 -0
- data/pgpool2/pool_ip.h +65 -0
- data/pgpool2/pool_ipc.h +38 -0
- data/pgpool2/pool_lobj.c +242 -0
- data/pgpool2/pool_lobj.h +32 -0
- data/pgpool2/pool_memqcache.c +3818 -0
- data/pgpool2/pool_memqcache.h +268 -0
- data/pgpool2/pool_params.c +163 -0
- data/pgpool2/pool_passwd.c +249 -0
- data/pgpool2/pool_passwd.h +41 -0
- data/pgpool2/pool_path.c +193 -0
- data/pgpool2/pool_path.h +81 -0
- data/pgpool2/pool_process_context.c +247 -0
- data/pgpool2/pool_process_context.h +62 -0
- data/pgpool2/pool_process_query.c +5001 -0
- data/pgpool2/pool_process_reporting.c +1671 -0
- data/pgpool2/pool_process_reporting.h +44 -0
- data/pgpool2/pool_proto2.c +671 -0
- data/pgpool2/pool_proto_modules.c +3524 -0
- data/pgpool2/pool_proto_modules.h +185 -0
- data/pgpool2/pool_query_cache.c +1020 -0
- data/pgpool2/pool_query_context.c +1871 -0
- data/pgpool2/pool_query_context.h +105 -0
- data/pgpool2/pool_relcache.c +284 -0
- data/pgpool2/pool_relcache.h +78 -0
- data/pgpool2/pool_rewrite_outfuncs.c +9060 -0
- data/pgpool2/pool_rewrite_query.c +715 -0
- data/pgpool2/pool_rewrite_query.h +192 -0
- data/pgpool2/pool_select_walker.c +1150 -0
- data/pgpool2/pool_select_walker.h +68 -0
- data/pgpool2/pool_sema.c +161 -0
- data/pgpool2/pool_session_context.c +952 -0
- data/pgpool2/pool_session_context.h +203 -0
- data/pgpool2/pool_shmem.c +185 -0
- data/pgpool2/pool_signal.c +158 -0
- data/pgpool2/pool_signal.h +61 -0
- data/pgpool2/pool_ssl.c +339 -0
- data/pgpool2/pool_stream.c +962 -0
- data/pgpool2/pool_stream.h +61 -0
- data/pgpool2/pool_system.c +659 -0
- data/pgpool2/pool_timestamp.c +1215 -0
- data/pgpool2/pool_timestamp.h +38 -0
- data/pgpool2/pool_type.h +171 -0
- data/pgpool2/pool_worker_child.c +384 -0
- data/pgpool2/ps_status.c +404 -0
- data/pgpool2/recovery.c +435 -0
- data/pgpool2/redhat/pgpool.conf.sample.patch +52 -0
- data/pgpool2/redhat/pgpool.init +201 -0
- data/pgpool2/redhat/pgpool.sysconfig +7 -0
- data/pgpool2/redhat/rpm_installer/basebackup-replication.sh +53 -0
- data/pgpool2/redhat/rpm_installer/basebackup-stream.sh +55 -0
- data/pgpool2/redhat/rpm_installer/config_for_script +17 -0
- data/pgpool2/redhat/rpm_installer/failover.sh +64 -0
- data/pgpool2/redhat/rpm_installer/getsources.sh +141 -0
- data/pgpool2/redhat/rpm_installer/install.sh +1363 -0
- data/pgpool2/redhat/rpm_installer/pgpool_recovery_pitr +47 -0
- data/pgpool2/redhat/rpm_installer/pgpool_remote_start +15 -0
- data/pgpool2/redhat/rpm_installer/recovery.conf +4 -0
- data/pgpool2/redhat/rpm_installer/uninstall.sh +57 -0
- data/pgpool2/sample/dist_def_pgbench.sql +73 -0
- data/pgpool2/sample/pgpool.pam +3 -0
- data/pgpool2/sample/pgpool_recovery +20 -0
- data/pgpool2/sample/pgpool_recovery_pitr +19 -0
- data/pgpool2/sample/pgpool_remote_start +13 -0
- data/pgpool2/sample/replicate_def_pgbench.sql +18 -0
- data/pgpool2/sql/insert_lock.sql +15 -0
- data/pgpool2/sql/pgpool-recovery/pgpool-recovery.c +280 -0
- data/pgpool2/sql/pgpool-recovery/pgpool-recovery.sql.in +19 -0
- data/pgpool2/sql/pgpool-recovery/pgpool_recovery--1.0.sql +24 -0
- data/pgpool2/sql/pgpool-recovery/pgpool_recovery.control +5 -0
- data/pgpool2/sql/pgpool-recovery/uninstall_pgpool-recovery.sql +3 -0
- data/pgpool2/sql/pgpool-regclass/pgpool-regclass.c +206 -0
- data/pgpool2/sql/pgpool-regclass/pgpool-regclass.sql.in +4 -0
- data/pgpool2/sql/pgpool-regclass/pgpool_regclass--1.0.sql +7 -0
- data/pgpool2/sql/pgpool-regclass/pgpool_regclass.control +5 -0
- data/pgpool2/sql/pgpool-regclass/uninstall_pgpool-regclass.sql +1 -0
- data/pgpool2/sql/system_db.sql +38 -0
- data/pgpool2/strlcpy.c +85 -0
- data/pgpool2/test/C/test_extended.c +98 -0
- data/pgpool2/test/jdbc/.cvsignore +2 -0
- data/pgpool2/test/jdbc/AutoCommitTest.java +45 -0
- data/pgpool2/test/jdbc/BatchTest.java +55 -0
- data/pgpool2/test/jdbc/ColumnTest.java +60 -0
- data/pgpool2/test/jdbc/CreateTempTableTest.java +48 -0
- data/pgpool2/test/jdbc/InsertTest.java +34 -0
- data/pgpool2/test/jdbc/LockTest.java +36 -0
- data/pgpool2/test/jdbc/PgpoolTest.java +75 -0
- data/pgpool2/test/jdbc/README.euc_jp +73 -0
- data/pgpool2/test/jdbc/RunTest.java +83 -0
- data/pgpool2/test/jdbc/SelectTest.java +37 -0
- data/pgpool2/test/jdbc/UpdateTest.java +32 -0
- data/pgpool2/test/jdbc/expected/CreateTempTable +1 -0
- data/pgpool2/test/jdbc/expected/autocommit +10 -0
- data/pgpool2/test/jdbc/expected/batch +1 -0
- data/pgpool2/test/jdbc/expected/column +100 -0
- data/pgpool2/test/jdbc/expected/insert +1 -0
- data/pgpool2/test/jdbc/expected/lock +100 -0
- data/pgpool2/test/jdbc/expected/select +2 -0
- data/pgpool2/test/jdbc/expected/update +1 -0
- data/pgpool2/test/jdbc/pgpool.properties +7 -0
- data/pgpool2/test/jdbc/prepare.sql +54 -0
- data/pgpool2/test/jdbc/run.sh +6 -0
- data/pgpool2/test/parser/.cvsignore +6 -0
- data/pgpool2/test/parser/README +32 -0
- data/pgpool2/test/parser/expected/copy.out +17 -0
- data/pgpool2/test/parser/expected/create.out +64 -0
- data/pgpool2/test/parser/expected/cursor.out +37 -0
- data/pgpool2/test/parser/expected/delete.out +10 -0
- data/pgpool2/test/parser/expected/drop.out +12 -0
- data/pgpool2/test/parser/expected/insert.out +13 -0
- data/pgpool2/test/parser/expected/misc.out +28 -0
- data/pgpool2/test/parser/expected/prepare.out +4 -0
- data/pgpool2/test/parser/expected/privileges.out +31 -0
- data/pgpool2/test/parser/expected/scanner.out +30 -0
- data/pgpool2/test/parser/expected/select.out +89 -0
- data/pgpool2/test/parser/expected/transaction.out +38 -0
- data/pgpool2/test/parser/expected/update.out +11 -0
- data/pgpool2/test/parser/expected/v84.out +37 -0
- data/pgpool2/test/parser/expected/v90.out +25 -0
- data/pgpool2/test/parser/expected/var.out +22 -0
- data/pgpool2/test/parser/input/alter.sql +2 -0
- data/pgpool2/test/parser/input/copy.sql +17 -0
- data/pgpool2/test/parser/input/create.sql +64 -0
- data/pgpool2/test/parser/input/cursor.sql +37 -0
- data/pgpool2/test/parser/input/delete.sql +10 -0
- data/pgpool2/test/parser/input/drop.sql +12 -0
- data/pgpool2/test/parser/input/insert.sql +13 -0
- data/pgpool2/test/parser/input/misc.sql +28 -0
- data/pgpool2/test/parser/input/prepare.sql +4 -0
- data/pgpool2/test/parser/input/privileges.sql +31 -0
- data/pgpool2/test/parser/input/scanner.sql +34 -0
- data/pgpool2/test/parser/input/select.sql +89 -0
- data/pgpool2/test/parser/input/transaction.sql +38 -0
- data/pgpool2/test/parser/input/update.sql +11 -0
- data/pgpool2/test/parser/input/v84.sql +37 -0
- data/pgpool2/test/parser/input/v90.sql +38 -0
- data/pgpool2/test/parser/input/var.sql +22 -0
- data/pgpool2/test/parser/main.c +96 -0
- data/pgpool2/test/parser/parse_schedule +16 -0
- data/pgpool2/test/parser/pool.h +13 -0
- data/pgpool2/test/parser/run-test +62 -0
- data/pgpool2/test/pdo-test/README.euc_jp +58 -0
- data/pgpool2/test/pdo-test/SQLlist/test1.sql +3 -0
- data/pgpool2/test/pdo-test/SQLlist/test2.sql +3 -0
- data/pgpool2/test/pdo-test/collections.inc +11 -0
- data/pgpool2/test/pdo-test/def.inc +7 -0
- data/pgpool2/test/pdo-test/log.txt +0 -0
- data/pgpool2/test/pdo-test/mod/database.inc +36 -0
- data/pgpool2/test/pdo-test/mod/def.inc +0 -0
- data/pgpool2/test/pdo-test/mod/errorhandler.inc +27 -0
- data/pgpool2/test/pdo-test/pdotest.php +11 -0
- data/pgpool2/test/pdo-test/regsql.inc +56 -0
- data/pgpool2/test/pgpool_setup +898 -0
- data/pgpool2/test/regression/README +39 -0
- data/pgpool2/test/regression/clean.sh +21 -0
- data/pgpool2/test/regression/libs.sh +16 -0
- data/pgpool2/test/regression/regress.sh +166 -0
- data/pgpool2/test/regression/tests/001.load_balance/test.sh +128 -0
- data/pgpool2/test/regression/tests/002.native_replication/PgTester.java +47 -0
- data/pgpool2/test/regression/tests/002.native_replication/create.sql +6 -0
- data/pgpool2/test/regression/tests/002.native_replication/test.sh +71 -0
- data/pgpool2/test/regression/tests/003.failover/expected.r +6 -0
- data/pgpool2/test/regression/tests/003.failover/expected.s +6 -0
- data/pgpool2/test/regression/tests/003.failover/test.sh +45 -0
- data/pgpool2/test/regression/tests/004.watchdog/master.conf +12 -0
- data/pgpool2/test/regression/tests/004.watchdog/standby.conf +19 -0
- data/pgpool2/test/regression/tests/004.watchdog/test.sh +52 -0
- data/pgpool2/test/regression/tests/050.bug58/test.sh +50 -0
- data/pgpool2/test/regression/tests/051.bug60/bug.sql +12 -0
- data/pgpool2/test/regression/tests/051.bug60/database-clean.sql +6 -0
- data/pgpool2/test/regression/tests/051.bug60/database-setup.sql +28 -0
- data/pgpool2/test/regression/tests/051.bug60/test.sh +79 -0
- data/pgpool2/test/regression/tests/052.do_query/test.sh +44 -0
- data/pgpool2/test/regression/tests/053.insert_lock_hangs/test.sh +81 -0
- data/pgpool2/test/regression/tests/054.postgres_fdw/test.sh +67 -0
- data/pgpool2/test/regression/tests/055.backend_all_down/test.sh +52 -0
- data/pgpool2/test/regression/tests/056.bug63/jdbctest2.java +66 -0
- data/pgpool2/test/regression/tests/056.bug63/test.sh +47 -0
- data/pgpool2/test/regression/tests/057.bug61/test.sh +40 -0
- data/pgpool2/test/regression/tests/058.bug68/jdbctest3.java +45 -0
- data/pgpool2/test/regression/tests/058.bug68/test.sh +47 -0
- data/pgpool2/test/timestamp/expected/insert.out +16 -0
- data/pgpool2/test/timestamp/expected/misc.out +3 -0
- data/pgpool2/test/timestamp/expected/update.out +6 -0
- data/pgpool2/test/timestamp/input/insert.sql +16 -0
- data/pgpool2/test/timestamp/input/misc.sql +3 -0
- data/pgpool2/test/timestamp/input/update.sql +6 -0
- data/pgpool2/test/timestamp/main.c +129 -0
- data/pgpool2/test/timestamp/parse_schedule +3 -0
- data/pgpool2/test/timestamp/run-test +69 -0
- data/pgpool2/version.h +1 -0
- data/pgpool2/watchdog/Makefile.am +17 -0
- data/pgpool2/watchdog/Makefile.in +505 -0
- data/pgpool2/watchdog/test/stab.c +266 -0
- data/pgpool2/watchdog/test/test.c +85 -0
- data/pgpool2/watchdog/test/wd_child_t.c +87 -0
- data/pgpool2/watchdog/test/wd_lifecheck_t.c +87 -0
- data/pgpool2/watchdog/test/wd_packet_t.c +87 -0
- data/pgpool2/watchdog/test/wd_ping_t.c +20 -0
- data/pgpool2/watchdog/watchdog.c +408 -0
- data/pgpool2/watchdog/watchdog.h +209 -0
- data/pgpool2/watchdog/wd_child.c +444 -0
- data/pgpool2/watchdog/wd_ext.h +123 -0
- data/pgpool2/watchdog/wd_heartbeat.c +577 -0
- data/pgpool2/watchdog/wd_if.c +216 -0
- data/pgpool2/watchdog/wd_init.c +126 -0
- data/pgpool2/watchdog/wd_interlock.c +347 -0
- data/pgpool2/watchdog/wd_lifecheck.c +512 -0
- data/pgpool2/watchdog/wd_list.c +429 -0
- data/pgpool2/watchdog/wd_packet.c +1159 -0
- data/pgpool2/watchdog/wd_ping.c +330 -0
- data/pgpool2/ylwrap +223 -0
- data/pgsql/presto_client.py +346 -0
- data/pgsql/prestogres.py +156 -0
- data/pgsql/setup_functions.sql +21 -0
- data/pgsql/setup_language.sql +3 -0
- data/prestogres.gemspec +23 -0
- metadata +496 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/* -*-pgsql-c-*- */
|
|
2
|
+
/*
|
|
3
|
+
*
|
|
4
|
+
* $Header$
|
|
5
|
+
*
|
|
6
|
+
* pgpool: a language independent connection pool server for PostgreSQL
|
|
7
|
+
* written by Tatsuo Ishii
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2003-2012 PgPool Global Development Group
|
|
10
|
+
*
|
|
11
|
+
* Permission to use, copy, modify, and distribute this software and
|
|
12
|
+
* its documentation for any purpose and without fee is hereby
|
|
13
|
+
* granted, provided that the above copyright notice appear in all
|
|
14
|
+
* copies and that both that copyright notice and this permission
|
|
15
|
+
* notice appear in supporting documentation, and that the name of the
|
|
16
|
+
* author not be used in advertising or publicity pertaining to
|
|
17
|
+
* distribution of the software without specific, written prior
|
|
18
|
+
* permission. The author makes no representations about the
|
|
19
|
+
* suitability of this software for any purpose. It is provided "as
|
|
20
|
+
* is" without express or implied warranty.
|
|
21
|
+
*
|
|
22
|
+
* pool_proto_modules.h.: header file for pool_proto_modules.c, pool_proto2.c
|
|
23
|
+
* and pool_process_query.c
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
#ifndef POOL_PROTO_MODULES_H
|
|
28
|
+
#define POOL_PROTO_MODULES_H
|
|
29
|
+
|
|
30
|
+
#include "parser/parser.h"
|
|
31
|
+
#include "parser/pool_memory.h"
|
|
32
|
+
#include "parser/pg_list.h"
|
|
33
|
+
#include "parser/parsenodes.h"
|
|
34
|
+
#include "pool_rewrite_query.h"
|
|
35
|
+
#include "pool_session_context.h"
|
|
36
|
+
#include "pool_process_reporting.h"
|
|
37
|
+
|
|
38
|
+
#define SPECIFIED_ERROR 1
|
|
39
|
+
#define POOL_DUMMY_WRITE_QUERY "DELETE FROM foo WHERE col = 'pgpool: unable to parse the query'"
|
|
40
|
+
#define POOL_DUMMY_READ_QUERY "SELECT 'pgpool: unable to parse the query'"
|
|
41
|
+
#define POOL_ERROR_QUERY "send invalid query from pgpool to abort transaction"
|
|
42
|
+
|
|
43
|
+
extern char *copy_table; /* copy table name */
|
|
44
|
+
extern char *copy_schema; /* copy table name */
|
|
45
|
+
extern char copy_delimiter; /* copy delimiter char */
|
|
46
|
+
extern char *copy_null; /* copy null string */
|
|
47
|
+
|
|
48
|
+
extern int is_select_pgcatalog;
|
|
49
|
+
extern int is_select_for_update; /* also for SELECT ... INTO */
|
|
50
|
+
extern bool is_parallel_table;
|
|
51
|
+
extern char *parsed_query;
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* modules defined in pool_proto_modules.c
|
|
55
|
+
*/
|
|
56
|
+
extern POOL_STATUS SimpleQuery(POOL_CONNECTION *frontend,
|
|
57
|
+
POOL_CONNECTION_POOL *backend,
|
|
58
|
+
int len, char *contents);
|
|
59
|
+
|
|
60
|
+
extern POOL_STATUS Execute(POOL_CONNECTION *frontend,
|
|
61
|
+
POOL_CONNECTION_POOL *backend,
|
|
62
|
+
int len, char *contents);
|
|
63
|
+
|
|
64
|
+
extern POOL_STATUS Parse(POOL_CONNECTION *frontend,
|
|
65
|
+
POOL_CONNECTION_POOL *backend,
|
|
66
|
+
int len, char *contents);
|
|
67
|
+
|
|
68
|
+
extern POOL_STATUS Bind(POOL_CONNECTION *frontend,
|
|
69
|
+
POOL_CONNECTION_POOL *backend,
|
|
70
|
+
int len, char *contents);
|
|
71
|
+
|
|
72
|
+
extern POOL_STATUS Describe(POOL_CONNECTION *frontend,
|
|
73
|
+
POOL_CONNECTION_POOL *backend,
|
|
74
|
+
int len, char *contents);
|
|
75
|
+
|
|
76
|
+
extern POOL_STATUS Close(POOL_CONNECTION *frontend,
|
|
77
|
+
POOL_CONNECTION_POOL *backend,
|
|
78
|
+
int len, char *contents);
|
|
79
|
+
|
|
80
|
+
extern POOL_STATUS FunctionCall3(POOL_CONNECTION *frontend,
|
|
81
|
+
POOL_CONNECTION_POOL *backend,
|
|
82
|
+
int len, char *contents);
|
|
83
|
+
|
|
84
|
+
extern POOL_STATUS ReadyForQuery(POOL_CONNECTION *frontend,
|
|
85
|
+
POOL_CONNECTION_POOL *backend, bool send_ready, bool cache_commit);
|
|
86
|
+
|
|
87
|
+
extern POOL_STATUS ParseComplete(POOL_CONNECTION *frontend,
|
|
88
|
+
POOL_CONNECTION_POOL *backend);
|
|
89
|
+
|
|
90
|
+
extern POOL_STATUS BindComplete(POOL_CONNECTION *frontend,
|
|
91
|
+
POOL_CONNECTION_POOL *backend);
|
|
92
|
+
|
|
93
|
+
extern POOL_STATUS CloseComplete(POOL_CONNECTION *frontend,
|
|
94
|
+
POOL_CONNECTION_POOL *backend);
|
|
95
|
+
|
|
96
|
+
extern POOL_STATUS CommandComplete(POOL_CONNECTION *frontend,
|
|
97
|
+
POOL_CONNECTION_POOL *backend);
|
|
98
|
+
|
|
99
|
+
extern POOL_STATUS ErrorResponse3(POOL_CONNECTION *frontend,
|
|
100
|
+
POOL_CONNECTION_POOL *backend);
|
|
101
|
+
|
|
102
|
+
extern POOL_STATUS CopyInResponse(POOL_CONNECTION *frontend,
|
|
103
|
+
POOL_CONNECTION_POOL *backend);
|
|
104
|
+
|
|
105
|
+
extern POOL_STATUS CopyOutResponse(POOL_CONNECTION *frontend,
|
|
106
|
+
POOL_CONNECTION_POOL *backend);
|
|
107
|
+
|
|
108
|
+
extern POOL_STATUS CopyDataRows(POOL_CONNECTION *frontend,
|
|
109
|
+
POOL_CONNECTION_POOL *backend, int copyin);
|
|
110
|
+
|
|
111
|
+
extern POOL_STATUS FunctionCall(POOL_CONNECTION *frontend,
|
|
112
|
+
POOL_CONNECTION_POOL *backend);
|
|
113
|
+
|
|
114
|
+
extern POOL_STATUS ProcessFrontendResponse(POOL_CONNECTION *frontend,
|
|
115
|
+
POOL_CONNECTION_POOL *backend);
|
|
116
|
+
|
|
117
|
+
extern POOL_STATUS ProcessBackendResponse(POOL_CONNECTION *frontend,
|
|
118
|
+
POOL_CONNECTION_POOL *backend,
|
|
119
|
+
int *state, short *num_fields);
|
|
120
|
+
|
|
121
|
+
/*
|
|
122
|
+
* modules defined in pool_proto2.c
|
|
123
|
+
*/
|
|
124
|
+
extern POOL_STATUS AsciiRow(POOL_CONNECTION *frontend,
|
|
125
|
+
POOL_CONNECTION_POOL *backend,
|
|
126
|
+
short num_fields);
|
|
127
|
+
|
|
128
|
+
extern POOL_STATUS BinaryRow(POOL_CONNECTION *frontend,
|
|
129
|
+
POOL_CONNECTION_POOL *backend,
|
|
130
|
+
short num_fields);
|
|
131
|
+
|
|
132
|
+
extern POOL_STATUS CompletedResponse(POOL_CONNECTION *frontend,
|
|
133
|
+
POOL_CONNECTION_POOL *backend);
|
|
134
|
+
|
|
135
|
+
extern POOL_STATUS CursorResponse(POOL_CONNECTION *frontend,
|
|
136
|
+
POOL_CONNECTION_POOL *backend);
|
|
137
|
+
|
|
138
|
+
extern POOL_STATUS EmptyQueryResponse(POOL_CONNECTION *frontend,
|
|
139
|
+
POOL_CONNECTION_POOL *backend);
|
|
140
|
+
|
|
141
|
+
extern POOL_STATUS FunctionResultResponse(POOL_CONNECTION *frontend,
|
|
142
|
+
POOL_CONNECTION_POOL *backend);
|
|
143
|
+
|
|
144
|
+
extern POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend,
|
|
145
|
+
POOL_CONNECTION_POOL *backend);
|
|
146
|
+
|
|
147
|
+
extern int RowDescription(POOL_CONNECTION *frontend,
|
|
148
|
+
POOL_CONNECTION_POOL *backend,
|
|
149
|
+
short *result);
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
extern POOL_STATUS wait_for_query_response(POOL_CONNECTION *frontend, POOL_CONNECTION *backend, int protoVersion);
|
|
153
|
+
extern int is_select_query(Node *node, char *sql);
|
|
154
|
+
extern bool is_commit_query(Node *node);
|
|
155
|
+
extern bool is_rollback_query(Node *node);
|
|
156
|
+
extern bool is_commit_or_rollback_query(Node *node);
|
|
157
|
+
extern bool is_strict_query(Node *node); /* returns non 0 if this is strict query */
|
|
158
|
+
extern int need_insert_lock(POOL_CONNECTION_POOL *backend, char *query, Node *node);
|
|
159
|
+
extern POOL_STATUS insert_lock(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, char *query, InsertStmt *node, int lock_kind);
|
|
160
|
+
extern char *parse_copy_data(char *buf, int len, char delimiter, int col_id);
|
|
161
|
+
extern int check_copy_from_stdin(Node *node); /* returns non 0 if this is a COPY FROM STDIN */
|
|
162
|
+
extern void query_ps_status(char *query, POOL_CONNECTION_POOL *backend); /* show ps status */
|
|
163
|
+
extern POOL_STATUS start_internal_transaction(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, Node *node);
|
|
164
|
+
extern POOL_STATUS end_internal_transaction(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
|
|
165
|
+
extern int detect_deadlock_error(POOL_CONNECTION *master, int major);
|
|
166
|
+
extern int detect_serialization_error(POOL_CONNECTION *master, int major, bool unread);
|
|
167
|
+
extern int detect_active_sql_transaction_error(POOL_CONNECTION *backend, int major);
|
|
168
|
+
extern int detect_query_cancel_error(POOL_CONNECTION *backend, int major);
|
|
169
|
+
extern bool is_partition_table(POOL_CONNECTION_POOL *backend, Node *node);
|
|
170
|
+
extern POOL_STATUS pool_discard_packet(POOL_CONNECTION_POOL *cp);
|
|
171
|
+
extern void query_cache_register(char kind, POOL_CONNECTION *frontend, char *database, char *data, int data_len);
|
|
172
|
+
extern int is_drop_database(Node *node); /* returns non 0 if this is a DROP DATABASE command */
|
|
173
|
+
|
|
174
|
+
extern POOL_STATUS send_simplequery_message(POOL_CONNECTION *backend, int len, char *string, int major);
|
|
175
|
+
extern POOL_STATUS send_extended_protocol_message(POOL_CONNECTION_POOL *backend,
|
|
176
|
+
int node_id, char *kind,
|
|
177
|
+
int len, char *string);
|
|
178
|
+
|
|
179
|
+
extern int synchronize(POOL_CONNECTION *cp);
|
|
180
|
+
extern POOL_STATUS read_kind_from_backend(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, char *decided_kind);
|
|
181
|
+
extern POOL_STATUS read_kind_from_one_backend(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, char *kind, int node);
|
|
182
|
+
extern POOL_STATUS do_error_command(POOL_CONNECTION *backend, int major);
|
|
183
|
+
extern POOL_STATUS raise_intentional_error_if_need(POOL_CONNECTION_POOL *backend);
|
|
184
|
+
|
|
185
|
+
#endif
|
|
@@ -0,0 +1,1020 @@
|
|
|
1
|
+
/* -*-pgsql-c-*- */
|
|
2
|
+
/*
|
|
3
|
+
* $Header$
|
|
4
|
+
*
|
|
5
|
+
* pgpool: a language independent connection pool server for PostgreSQL
|
|
6
|
+
* written by Tatsuo Ishii
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2003-2010 PgPool Global Development Group
|
|
9
|
+
*
|
|
10
|
+
* Permission to use, copy, modify, and distribute this software and
|
|
11
|
+
* its documentation for any purpose and without fee is hereby
|
|
12
|
+
* granted, provided that the above copyright notice appear in all
|
|
13
|
+
* copies and that both that copyright notice and this permission
|
|
14
|
+
* notice appear in supporting documentation, and that the name of the
|
|
15
|
+
* author not be used in advertising or publicity pertaining to
|
|
16
|
+
* distribution of the software without specific, written prior
|
|
17
|
+
* permission. The author makes no representations about the
|
|
18
|
+
* suitability of this software for any purpose. It is provided "as
|
|
19
|
+
* is" without express or implied warranty.
|
|
20
|
+
*
|
|
21
|
+
* pool_query_cache.c: query cache
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
#include <errno.h>
|
|
26
|
+
#include <stdlib.h>
|
|
27
|
+
#include <string.h>
|
|
28
|
+
#include <sys/types.h>
|
|
29
|
+
#include <netinet/in.h>
|
|
30
|
+
#include <arpa/inet.h>
|
|
31
|
+
#include <time.h>
|
|
32
|
+
#include <sys/time.h>
|
|
33
|
+
#include <unistd.h>
|
|
34
|
+
#ifdef HAVE_SYS_SELECT_H
|
|
35
|
+
#include <sys/select.h>
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#include "pool.h"
|
|
39
|
+
#include "md5.h"
|
|
40
|
+
#include "pool_stream.h"
|
|
41
|
+
#include "pool_config.h"
|
|
42
|
+
#include "pool_proto_modules.h"
|
|
43
|
+
#include "parser/parsenodes.h"
|
|
44
|
+
|
|
45
|
+
#define QUERY_CACHE_TABLE_NAME "query_cache"
|
|
46
|
+
#define CACHE_REGISTER_PREPARED_STMT "register_prepared_stmt"
|
|
47
|
+
#define DEFAULT_CACHE_SIZE 8192
|
|
48
|
+
|
|
49
|
+
#define SYSDB_CON (SYSDB_CONNECTION->con)
|
|
50
|
+
#define SYSDB_MAJOR (SYSDB_CONNECTION->sp->major)
|
|
51
|
+
#define CACHE_TABLE_INFO (SYSDB_INFO->query_cache_table_info)
|
|
52
|
+
|
|
53
|
+
/* data structure to store RowDescription and DataRow cache */
|
|
54
|
+
typedef struct
|
|
55
|
+
{
|
|
56
|
+
char *md5_query; /* query in md5 hushed format*/
|
|
57
|
+
char *query; /* query string */
|
|
58
|
+
char *cache; /* cached data */
|
|
59
|
+
int cache_size; /* cached data size */
|
|
60
|
+
int cache_offset; /* points the end of cache */
|
|
61
|
+
char *db_name; /* database name */
|
|
62
|
+
char *create_time; /* cache create timestamp in ISO format */
|
|
63
|
+
} QueryCacheInfo;
|
|
64
|
+
|
|
65
|
+
typedef enum
|
|
66
|
+
{
|
|
67
|
+
CACHE_FOUND, CACHE_NOT_FOUND, CACHE_ERROR
|
|
68
|
+
} CACHE_STATUS;
|
|
69
|
+
|
|
70
|
+
static QueryCacheInfo *query_cache_info;
|
|
71
|
+
|
|
72
|
+
static CACHE_STATUS search_system_db_for_cache(POOL_CONNECTION *frontend, char *sql, int sql_len, struct timeval *t, char tstate);
|
|
73
|
+
static int ForwardCacheToFrontend(POOL_CONNECTION *frontend, char *cache, char tstate);
|
|
74
|
+
static int init_query_cache_info(POOL_CONNECTION *pc, char *database, char *query);
|
|
75
|
+
static void free_query_cache_info(void);
|
|
76
|
+
static int malloc_failed(void *p);
|
|
77
|
+
static int write_cache(void *buf, int len);
|
|
78
|
+
static char *pq_time_to_str(time_t t);
|
|
79
|
+
static int system_db_connection_exists(void);
|
|
80
|
+
static void define_prepared_statements(void);
|
|
81
|
+
|
|
82
|
+
/* --------------------------------
|
|
83
|
+
* pool_clear_cache - clears cache data from the SystemDB
|
|
84
|
+
*
|
|
85
|
+
* return 0 on success, -1 otherwise
|
|
86
|
+
* --------------------------------
|
|
87
|
+
*/
|
|
88
|
+
int
|
|
89
|
+
pool_clear_cache_by_time(Interval *interval, int size)
|
|
90
|
+
{
|
|
91
|
+
PGresult *pg_result = NULL;
|
|
92
|
+
long interval_in_days = 0;
|
|
93
|
+
long interval_in_seconds = 0;
|
|
94
|
+
time_t query_delete_timepoint;
|
|
95
|
+
char *query_delete_timepoint_in_str = NULL;
|
|
96
|
+
int sql_len;
|
|
97
|
+
char *sql = NULL;
|
|
98
|
+
int i;
|
|
99
|
+
|
|
100
|
+
if (! system_db_connection_exists())
|
|
101
|
+
return -1;
|
|
102
|
+
|
|
103
|
+
for (i = 0; i < size; i++)
|
|
104
|
+
{
|
|
105
|
+
int q = interval[i].quantity;
|
|
106
|
+
|
|
107
|
+
switch (interval[i].unit)
|
|
108
|
+
{
|
|
109
|
+
case millennium:
|
|
110
|
+
case millenniums:
|
|
111
|
+
q *= 10;
|
|
112
|
+
|
|
113
|
+
case century:
|
|
114
|
+
case centuries:
|
|
115
|
+
q *= 10;
|
|
116
|
+
|
|
117
|
+
case decade:
|
|
118
|
+
case decades:
|
|
119
|
+
q *= 10;
|
|
120
|
+
|
|
121
|
+
case year:
|
|
122
|
+
case years:
|
|
123
|
+
q *= 12;
|
|
124
|
+
|
|
125
|
+
case month:
|
|
126
|
+
case months:
|
|
127
|
+
q *= 31; /* should I change this according to the month? */
|
|
128
|
+
interval_in_days += q;
|
|
129
|
+
break;
|
|
130
|
+
|
|
131
|
+
case week:
|
|
132
|
+
case weeks:
|
|
133
|
+
q *= 7;
|
|
134
|
+
|
|
135
|
+
case day:
|
|
136
|
+
case days:
|
|
137
|
+
q *= 24;
|
|
138
|
+
|
|
139
|
+
case hour:
|
|
140
|
+
case hours:
|
|
141
|
+
q *= 60;
|
|
142
|
+
|
|
143
|
+
case minute:
|
|
144
|
+
case minutes:
|
|
145
|
+
q *= 60;
|
|
146
|
+
|
|
147
|
+
case second:
|
|
148
|
+
case seconds:
|
|
149
|
+
interval_in_seconds += q;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
interval_in_seconds = (interval_in_days * 86400) + interval_in_seconds;
|
|
155
|
+
query_delete_timepoint = time(NULL) - interval_in_seconds;
|
|
156
|
+
|
|
157
|
+
query_delete_timepoint_in_str = pq_time_to_str(query_delete_timepoint);
|
|
158
|
+
if (malloc_failed(query_delete_timepoint_in_str))
|
|
159
|
+
return -1;
|
|
160
|
+
|
|
161
|
+
sql_len =
|
|
162
|
+
strlen(pool_config->system_db_schema) +
|
|
163
|
+
strlen(QUERY_CACHE_TABLE_NAME) +
|
|
164
|
+
strlen(query_delete_timepoint_in_str) +
|
|
165
|
+
64;
|
|
166
|
+
|
|
167
|
+
sql = (char *)malloc(sql_len);
|
|
168
|
+
if (malloc_failed(sql))
|
|
169
|
+
{
|
|
170
|
+
free(query_delete_timepoint_in_str);
|
|
171
|
+
return -1;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
snprintf(sql, sql_len,
|
|
175
|
+
"DELETE FROM %s.%s WHERE create_time <= '%s'",
|
|
176
|
+
pool_config->system_db_schema,
|
|
177
|
+
QUERY_CACHE_TABLE_NAME,
|
|
178
|
+
query_delete_timepoint_in_str);
|
|
179
|
+
|
|
180
|
+
pool_debug("pool_clear_cache: delete all query cache created before '%s'", query_delete_timepoint_in_str);
|
|
181
|
+
|
|
182
|
+
pg_result = PQexec(system_db_info->pgconn, sql);
|
|
183
|
+
if (!pg_result || PQresultStatus(pg_result) != PGRES_COMMAND_OK)
|
|
184
|
+
{
|
|
185
|
+
pool_error("pool_clear_cache: PQexec() failed. reason: %s",
|
|
186
|
+
PQerrorMessage(system_db_info->pgconn));
|
|
187
|
+
|
|
188
|
+
PQclear(pg_result);
|
|
189
|
+
free(query_delete_timepoint_in_str);
|
|
190
|
+
free(sql);
|
|
191
|
+
return -1;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
PQclear(pg_result);
|
|
195
|
+
free(query_delete_timepoint_in_str);
|
|
196
|
+
free(sql);
|
|
197
|
+
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* --------------------------------
|
|
202
|
+
* pool_query_cache_table_exists - checks if query_cache table exists in the SystemDB
|
|
203
|
+
*
|
|
204
|
+
* This function is called once and only once from the pgpool parent process.
|
|
205
|
+
* return 1 if query_cache table exists, 0 otherwise.
|
|
206
|
+
* --------------------------------
|
|
207
|
+
*/
|
|
208
|
+
int
|
|
209
|
+
pool_query_cache_table_exists(void)
|
|
210
|
+
{
|
|
211
|
+
PGresult *pg_result = NULL;
|
|
212
|
+
char *sql = NULL;
|
|
213
|
+
int sql_len = strlen(pool_config->system_db_schema) + strlen(QUERY_CACHE_TABLE_NAME) + 64;
|
|
214
|
+
|
|
215
|
+
if (! system_db_connection_exists())
|
|
216
|
+
return 0;
|
|
217
|
+
|
|
218
|
+
sql = (char *)malloc(sql_len);
|
|
219
|
+
if (malloc_failed(sql))
|
|
220
|
+
return 0;
|
|
221
|
+
|
|
222
|
+
snprintf(sql, sql_len,
|
|
223
|
+
"SELECT hash, query, value, dbname, create_time FROM %s.%s LIMIT 1",
|
|
224
|
+
pool_config->system_db_schema,
|
|
225
|
+
QUERY_CACHE_TABLE_NAME);
|
|
226
|
+
|
|
227
|
+
pg_result = PQexec(system_db_info->pgconn, sql);
|
|
228
|
+
if (!pg_result || PQresultStatus(pg_result) != PGRES_TUPLES_OK)
|
|
229
|
+
{
|
|
230
|
+
pool_error("pool_query_cache_table_exists: PQexec() failed. reason: %s",
|
|
231
|
+
PQerrorMessage(system_db_info->pgconn));
|
|
232
|
+
|
|
233
|
+
PQclear(pg_result);
|
|
234
|
+
free(sql);
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
PQclear(pg_result);
|
|
239
|
+
pool_close_libpq_connection();
|
|
240
|
+
free(sql);
|
|
241
|
+
|
|
242
|
+
return 1;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* --------------------------------
|
|
246
|
+
* pool_query_cache_lookup - retrieve query cache from the SystemDB
|
|
247
|
+
*
|
|
248
|
+
* creates a SQL query string for searching a cache from the SystemDB.
|
|
249
|
+
*
|
|
250
|
+
* returns POOL_CONTINUE if cache is found. returns POOL_END if cache was
|
|
251
|
+
* not found. returns POOL_ERROR if an error has been encountered while
|
|
252
|
+
* searching.
|
|
253
|
+
*
|
|
254
|
+
* Note that POOL_END and POOL_ERROR are treated the same by the caller
|
|
255
|
+
* (pool_process_query.c).
|
|
256
|
+
* POOL_END and POOL_ERROR both indicates to the caller that the search
|
|
257
|
+
* query must be forwarded to the backends in order to retrieve data and
|
|
258
|
+
* the result be cached.
|
|
259
|
+
* Only difference is that POOL_ERROR indicates that some fatal error has
|
|
260
|
+
* occurred; query cache function, however, should be seamless to the user
|
|
261
|
+
* whether cache was not found or error has occurred during cache retrieve.
|
|
262
|
+
* --------------------------------
|
|
263
|
+
*/
|
|
264
|
+
POOL_STATUS
|
|
265
|
+
pool_query_cache_lookup(POOL_CONNECTION *frontend, char *query, char *database, char tstate)
|
|
266
|
+
{
|
|
267
|
+
char *sql = NULL;
|
|
268
|
+
int sql_len;
|
|
269
|
+
char md5_query[33];
|
|
270
|
+
struct timeval timeout;
|
|
271
|
+
int status;
|
|
272
|
+
|
|
273
|
+
if (! system_db_connection_exists())
|
|
274
|
+
return POOL_ERROR; /* same as POOL_END ... at least for now */
|
|
275
|
+
|
|
276
|
+
sql_len =
|
|
277
|
+
strlen(pool_config->system_db_schema) +
|
|
278
|
+
strlen(QUERY_CACHE_TABLE_NAME) +
|
|
279
|
+
sizeof(md5_query) +
|
|
280
|
+
strlen(database) +
|
|
281
|
+
64;
|
|
282
|
+
sql = (char *)malloc(sql_len);
|
|
283
|
+
if (malloc_failed(sql))
|
|
284
|
+
return POOL_ERROR; /* should I exit here rather than returning an error? */
|
|
285
|
+
|
|
286
|
+
/* cached data lookup */
|
|
287
|
+
pool_md5_hash(query, strlen(query), md5_query);
|
|
288
|
+
snprintf(sql, sql_len, "SELECT value FROM %s.%s WHERE hash = '%s' AND dbname = '%s'",
|
|
289
|
+
pool_config->system_db_schema,
|
|
290
|
+
QUERY_CACHE_TABLE_NAME,
|
|
291
|
+
md5_query,
|
|
292
|
+
database);
|
|
293
|
+
|
|
294
|
+
/* set timeout value for select */
|
|
295
|
+
timeout.tv_sec = pool_config->child_life_time;
|
|
296
|
+
timeout.tv_usec = 0;
|
|
297
|
+
|
|
298
|
+
pool_debug("pool_query_cache_lookup: searching cache for query: \"%s\"", query);
|
|
299
|
+
status = search_system_db_for_cache(frontend, sql, strlen(sql)+1, &timeout, tstate);
|
|
300
|
+
|
|
301
|
+
/* make sure that the remaining data is discarded */
|
|
302
|
+
SYSDB_CON->po = 0;
|
|
303
|
+
SYSDB_CON->len = 0;
|
|
304
|
+
|
|
305
|
+
free(sql);
|
|
306
|
+
|
|
307
|
+
/* cache found, and no backend communication needed */
|
|
308
|
+
if (status == CACHE_FOUND)
|
|
309
|
+
{
|
|
310
|
+
return POOL_CONTINUE;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* cache not found */
|
|
314
|
+
|
|
315
|
+
if (status == CACHE_ERROR)
|
|
316
|
+
{
|
|
317
|
+
pool_error("pool_query_cache_lookup: query cache lookup failed");
|
|
318
|
+
/* reset the SystemDB connection */
|
|
319
|
+
if (system_db_info->pgconn)
|
|
320
|
+
pool_close_libpq_connection();
|
|
321
|
+
return POOL_ERROR; /* same as POOL_END ... at least for now */
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
pool_debug("pool_query_cache_lookup: query cache not found");
|
|
325
|
+
return POOL_END;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/* --------------------------------
|
|
329
|
+
* search_system_db_for_cache - search for query cache in libpq protocol level
|
|
330
|
+
*
|
|
331
|
+
* sends a cache searching query string using libpq protocol to the SystemDB.
|
|
332
|
+
* if the SystemDB returns cache, forward the data to the frontend, and return
|
|
333
|
+
* CACHE_FOUND. if cache was not found, silently discards the remaining data
|
|
334
|
+
* returned by the SystemDB, and return CACHE_NOT_FOUND. returns CACHE_ERROR
|
|
335
|
+
* if an error was encountered.
|
|
336
|
+
* --------------------------------
|
|
337
|
+
*/
|
|
338
|
+
static CACHE_STATUS
|
|
339
|
+
search_system_db_for_cache(POOL_CONNECTION *frontend, char *sql, int sql_len, struct timeval *t, char tstate)
|
|
340
|
+
{
|
|
341
|
+
fd_set readmask;
|
|
342
|
+
int fds;
|
|
343
|
+
int num_fds;
|
|
344
|
+
struct timeval *timeout = NULL;
|
|
345
|
+
char kind;
|
|
346
|
+
int readlen;
|
|
347
|
+
char *data = NULL;
|
|
348
|
+
CACHE_STATUS return_value = CACHE_ERROR;
|
|
349
|
+
int cache_found = 0;
|
|
350
|
+
|
|
351
|
+
pool_debug("pool_query_cache_lookup: executing query: \"%s\"", sql);
|
|
352
|
+
|
|
353
|
+
pool_write(SYSDB_CON, "Q", 1);
|
|
354
|
+
if (SYSDB_MAJOR == PROTO_MAJOR_V3)
|
|
355
|
+
{
|
|
356
|
+
int sendlen = htonl(sql_len + 4);
|
|
357
|
+
pool_write(SYSDB_CON, &sendlen, sizeof(sendlen));
|
|
358
|
+
}
|
|
359
|
+
if (pool_write_and_flush(SYSDB_CON, sql, sql_len) < 0)
|
|
360
|
+
{
|
|
361
|
+
pool_error("pool_query_cache_lookup: error while sending data to the SystemDB");
|
|
362
|
+
return CACHE_ERROR;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if ((t->tv_sec + t->tv_usec) == 0)
|
|
366
|
+
timeout = NULL;
|
|
367
|
+
else
|
|
368
|
+
timeout = t;
|
|
369
|
+
|
|
370
|
+
/* don't really need select() or for(;;) here, but we may need it someday... or not */
|
|
371
|
+
for (;;)
|
|
372
|
+
{
|
|
373
|
+
FD_ZERO(&readmask);
|
|
374
|
+
num_fds = 0;
|
|
375
|
+
|
|
376
|
+
num_fds = SYSDB_CON->fd + 1;
|
|
377
|
+
FD_SET(SYSDB_CON->fd, &readmask);
|
|
378
|
+
fds = select(num_fds, &readmask, NULL, NULL, timeout);
|
|
379
|
+
if (fds == -1)
|
|
380
|
+
{
|
|
381
|
+
if (errno == EINTR)
|
|
382
|
+
continue;
|
|
383
|
+
|
|
384
|
+
pool_error("pool_query_cache_lookup: select() failed. reason: %s", strerror(errno));
|
|
385
|
+
return CACHE_ERROR;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/* select() timeout */
|
|
389
|
+
if (fds == 0)
|
|
390
|
+
return CACHE_ERROR;
|
|
391
|
+
|
|
392
|
+
for (;;)
|
|
393
|
+
{
|
|
394
|
+
if (! FD_ISSET(SYSDB_CON->fd, &readmask))
|
|
395
|
+
{
|
|
396
|
+
pool_error("pool_query_cache_lookup: select() failed");
|
|
397
|
+
return CACHE_ERROR;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/* read kind */
|
|
401
|
+
if (pool_read(SYSDB_CON, &kind, sizeof(kind)) < 0)
|
|
402
|
+
{
|
|
403
|
+
pool_error("pool_query_cache_lookup: error while reading message kind");
|
|
404
|
+
return CACHE_ERROR;
|
|
405
|
+
}
|
|
406
|
+
pool_debug("pool_query_cache_lookup: received %c from systemdb", kind);
|
|
407
|
+
|
|
408
|
+
/* just do the routine work of reading data in. data won't be used */
|
|
409
|
+
if (kind == 'T')
|
|
410
|
+
{
|
|
411
|
+
if (SYSDB_MAJOR == PROTO_MAJOR_V3)
|
|
412
|
+
{
|
|
413
|
+
if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0)
|
|
414
|
+
{
|
|
415
|
+
pool_error("pool_query_cache_lookup: error while reading message length");
|
|
416
|
+
return CACHE_ERROR;
|
|
417
|
+
}
|
|
418
|
+
readlen = ntohl(readlen) - sizeof(int);
|
|
419
|
+
data = pool_read2(SYSDB_CON, readlen);
|
|
420
|
+
}
|
|
421
|
+
else
|
|
422
|
+
{
|
|
423
|
+
data = pool_read_string(SYSDB_CON, &readlen, 0);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
else if (kind == 'D') /* cache found! forward it to the frontend */
|
|
427
|
+
{
|
|
428
|
+
char *cache;
|
|
429
|
+
int status;
|
|
430
|
+
|
|
431
|
+
cache_found = 1;
|
|
432
|
+
|
|
433
|
+
if (SYSDB_MAJOR == PROTO_MAJOR_V3)
|
|
434
|
+
{
|
|
435
|
+
if (pool_read(SYSDB_CON, &readlen, sizeof(readlen)) < 0)
|
|
436
|
+
{
|
|
437
|
+
pool_error("pool_query_cache_lookup: error while reading message length");
|
|
438
|
+
return CACHE_ERROR;
|
|
439
|
+
}
|
|
440
|
+
readlen = ntohl(readlen) - sizeof(int);
|
|
441
|
+
cache = pool_read2(SYSDB_CON, readlen);
|
|
442
|
+
}
|
|
443
|
+
else
|
|
444
|
+
{
|
|
445
|
+
cache = pool_read_string(SYSDB_CON, &readlen, 0);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (cache == NULL)
|
|
449
|
+
{
|
|
450
|
+
pool_error("pool_query_cache_lookup: error while reading message body");
|
|
451
|
+
return CACHE_ERROR;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
cache[readlen] = '\0';
|
|
455
|
+
|
|
456
|
+
cache += sizeof(short); /* number of columns in 'D' (we know it's always going to be 1, so skip) */
|
|
457
|
+
cache += sizeof(int); /* length of escaped bytea cache in string format. don't need the length */
|
|
458
|
+
|
|
459
|
+
status = ForwardCacheToFrontend(frontend, cache, tstate);
|
|
460
|
+
if (status < 0)
|
|
461
|
+
{
|
|
462
|
+
/* fatal error has occurred while forwarding cache */
|
|
463
|
+
pool_error("pool_query_cache_lookup: query cache forwarding failed");
|
|
464
|
+
return_value = CACHE_ERROR;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
else if (kind == 'C') /* see if 'D' was received */
|
|
468
|
+
{
|
|
469
|
+
if (cache_found)
|
|
470
|
+
return_value = CACHE_FOUND;
|
|
471
|
+
else
|
|
472
|
+
return_value = CACHE_NOT_FOUND;
|
|
473
|
+
|
|
474
|
+
/* must discard the remaining data */
|
|
475
|
+
if (SYSDB_MAJOR == PROTO_MAJOR_V3)
|
|
476
|
+
{
|
|
477
|
+
if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0)
|
|
478
|
+
{
|
|
479
|
+
pool_error("pool_query_cache_lookup: error while reading message length");
|
|
480
|
+
return CACHE_ERROR;
|
|
481
|
+
}
|
|
482
|
+
readlen = ntohl(readlen) - sizeof(int);
|
|
483
|
+
data = pool_read2(SYSDB_CON, readlen);
|
|
484
|
+
}
|
|
485
|
+
else
|
|
486
|
+
{
|
|
487
|
+
data = pool_read_string(SYSDB_CON, &readlen, 0);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
else if (kind == 'Z')
|
|
491
|
+
{
|
|
492
|
+
/* must discard the remaining data */
|
|
493
|
+
if (SYSDB_MAJOR == PROTO_MAJOR_V3)
|
|
494
|
+
{
|
|
495
|
+
if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0)
|
|
496
|
+
{
|
|
497
|
+
pool_error("pool_query_cache_lookup: error while reading message length");
|
|
498
|
+
return CACHE_ERROR;
|
|
499
|
+
}
|
|
500
|
+
readlen = ntohl(readlen) - sizeof(int);
|
|
501
|
+
data = pool_read2(SYSDB_CON, readlen);
|
|
502
|
+
}
|
|
503
|
+
else
|
|
504
|
+
{
|
|
505
|
+
data = pool_read_string(SYSDB_CON, &readlen, 0);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
else if (kind == 'E')
|
|
511
|
+
{
|
|
512
|
+
/* must discard the remaining data */
|
|
513
|
+
if (SYSDB_MAJOR == PROTO_MAJOR_V3)
|
|
514
|
+
{
|
|
515
|
+
if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0)
|
|
516
|
+
{
|
|
517
|
+
pool_error("pool_query_cache_lookup: error while reading message length");
|
|
518
|
+
return CACHE_ERROR;
|
|
519
|
+
}
|
|
520
|
+
readlen = ntohl(readlen) - sizeof(int);
|
|
521
|
+
data = pool_read2(SYSDB_CON, readlen);
|
|
522
|
+
}
|
|
523
|
+
else
|
|
524
|
+
{
|
|
525
|
+
data = pool_read_string(SYSDB_CON, &readlen, 0);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
return_value = CACHE_ERROR;
|
|
529
|
+
}
|
|
530
|
+
else
|
|
531
|
+
{
|
|
532
|
+
/* shouldn't get here, but just in case */
|
|
533
|
+
return CACHE_ERROR;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
return return_value;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/* --------------------------------
|
|
544
|
+
* ForwardCacheToFrontend - simply forwards cached data to the frontend
|
|
545
|
+
*
|
|
546
|
+
* since the cached data passed from the caller is in escaped binary string
|
|
547
|
+
* format, unescape it and send it to the frontend appending 'Z' at the end.
|
|
548
|
+
* returns 0 on success, -1 otherwise.
|
|
549
|
+
* --------------------------------
|
|
550
|
+
*/
|
|
551
|
+
static int ForwardCacheToFrontend(POOL_CONNECTION *frontend, char *cache, char tstate)
|
|
552
|
+
{
|
|
553
|
+
int sendlen;
|
|
554
|
+
size_t sz;
|
|
555
|
+
char *binary_cache = NULL;
|
|
556
|
+
|
|
557
|
+
binary_cache = (char *)PQunescapeBytea((unsigned char *)cache, &sz);
|
|
558
|
+
sendlen = (int) sz;
|
|
559
|
+
if (malloc_failed(binary_cache))
|
|
560
|
+
return -1;
|
|
561
|
+
|
|
562
|
+
pool_debug("ForwardCacheToFrontend: query cache found (%d bytes)", sendlen);
|
|
563
|
+
|
|
564
|
+
/* forward cache to the frontend */
|
|
565
|
+
pool_write(frontend, binary_cache, sendlen);
|
|
566
|
+
|
|
567
|
+
/* send ReadyForQuery to the frontend*/
|
|
568
|
+
pool_write(frontend, "Z", 1);
|
|
569
|
+
sendlen = htonl(5);
|
|
570
|
+
pool_write(frontend, &sendlen, sizeof(int));
|
|
571
|
+
if (pool_write_and_flush(frontend, &tstate, 1) < 0)
|
|
572
|
+
{
|
|
573
|
+
pool_error("pool_query_cache_lookup: error while writing data to the frontend");
|
|
574
|
+
PQfreemem(binary_cache);
|
|
575
|
+
return -1;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
PQfreemem(binary_cache);
|
|
579
|
+
return 0;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/* --------------------------------
|
|
583
|
+
* pool_query_cache_register() - register query cache to the SystemDB
|
|
584
|
+
*
|
|
585
|
+
* returns 0 on success, -1 otherwise
|
|
586
|
+
* --------------------------------
|
|
587
|
+
*/
|
|
588
|
+
int
|
|
589
|
+
pool_query_cache_register(char kind,
|
|
590
|
+
POOL_CONNECTION *frontend,
|
|
591
|
+
char *database,
|
|
592
|
+
char *data,
|
|
593
|
+
int data_len,
|
|
594
|
+
char *query)
|
|
595
|
+
{
|
|
596
|
+
int ret;
|
|
597
|
+
int send_len;
|
|
598
|
+
|
|
599
|
+
if (! system_db_connection_exists())
|
|
600
|
+
return -1;
|
|
601
|
+
if (! CACHE_TABLE_INFO.has_prepared_statement)
|
|
602
|
+
define_prepared_statements();
|
|
603
|
+
|
|
604
|
+
switch (kind)
|
|
605
|
+
{
|
|
606
|
+
case 'T': /* RowDescription */
|
|
607
|
+
{
|
|
608
|
+
/* for all SELECT result data from the backend, 'T' must come first */
|
|
609
|
+
if (query_cache_info != NULL)
|
|
610
|
+
{
|
|
611
|
+
pool_error("pool_query_cache_register: received RowDescription in the wrong order");
|
|
612
|
+
free_query_cache_info();
|
|
613
|
+
return -1;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
pool_debug("pool_query_cache_register: saving cache for query: \"%s\"", query);
|
|
617
|
+
|
|
618
|
+
/* initialize query_cache_info and save the query */
|
|
619
|
+
ret = init_query_cache_info(frontend, database, query);
|
|
620
|
+
if (ret)
|
|
621
|
+
return ret;
|
|
622
|
+
|
|
623
|
+
/* store data into the cache */
|
|
624
|
+
write_cache(&kind, 1);
|
|
625
|
+
send_len = htonl(data_len + sizeof(int));
|
|
626
|
+
write_cache(&send_len, sizeof(int));
|
|
627
|
+
write_cache(data, data_len);
|
|
628
|
+
|
|
629
|
+
break;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
case 'D': /* DataRow */
|
|
633
|
+
{
|
|
634
|
+
/* for all SELECT result data from the backend, 'T' must come first */
|
|
635
|
+
if (query_cache_info == NULL)
|
|
636
|
+
{
|
|
637
|
+
pool_error("pool_query_cache_register: received DataRow in the wrong order");
|
|
638
|
+
return -1;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
write_cache(&kind, 1);
|
|
642
|
+
send_len = htonl(data_len + sizeof(int));
|
|
643
|
+
write_cache(&send_len, sizeof(int));
|
|
644
|
+
write_cache(data, data_len);
|
|
645
|
+
|
|
646
|
+
break;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
case 'C': /* CommandComplete */
|
|
650
|
+
{
|
|
651
|
+
PGresult *pg_result = NULL;
|
|
652
|
+
char *escaped_query = NULL;
|
|
653
|
+
size_t escaped_query_len;
|
|
654
|
+
time_t now = time(NULL);
|
|
655
|
+
char *values[5];
|
|
656
|
+
int values_len[5];
|
|
657
|
+
int values_format[5];
|
|
658
|
+
int i;
|
|
659
|
+
|
|
660
|
+
/* for all SELECT result data from the backend, 'T' must come first */
|
|
661
|
+
if (query_cache_info == NULL)
|
|
662
|
+
{
|
|
663
|
+
pool_error("pool_query_cache_register: received CommandComplete in the wrong order");
|
|
664
|
+
return -1;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/* pack CommandComplete data into the cache */
|
|
668
|
+
write_cache(&kind, 1);
|
|
669
|
+
send_len = htonl(data_len + sizeof(int));
|
|
670
|
+
write_cache(&send_len, sizeof(int));
|
|
671
|
+
write_cache(data, data_len);
|
|
672
|
+
|
|
673
|
+
query_cache_info->create_time = pq_time_to_str(now);
|
|
674
|
+
if (malloc_failed(query_cache_info->create_time))
|
|
675
|
+
{
|
|
676
|
+
free_query_cache_info();
|
|
677
|
+
return -1;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
escaped_query = (char *)malloc(strlen(query_cache_info->query) * 2 + 1);
|
|
681
|
+
if (malloc_failed(escaped_query))
|
|
682
|
+
{
|
|
683
|
+
free_query_cache_info();
|
|
684
|
+
return -1;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/* escaped_query_len = PQescapeStringConn(system_db_info->pgconn, */
|
|
688
|
+
/* escaped_query, */
|
|
689
|
+
/* query_cache_info->query, */
|
|
690
|
+
/* strlen(query_cache_info->query))); */
|
|
691
|
+
escaped_query_len = PQescapeString(escaped_query, query_cache_info->query, strlen(query_cache_info->query));
|
|
692
|
+
|
|
693
|
+
/* all the result data have been received. store into the SystemDB */
|
|
694
|
+
values[0] = strdup(query_cache_info->md5_query);
|
|
695
|
+
values[1] = strdup(escaped_query);
|
|
696
|
+
values[2] = (char *)malloc(query_cache_info->cache_offset);
|
|
697
|
+
memcpy(values[2], query_cache_info->cache, query_cache_info->cache_offset);
|
|
698
|
+
values[3] = strdup(query_cache_info->db_name);
|
|
699
|
+
values[4] = strdup(query_cache_info->create_time);
|
|
700
|
+
for (i = 0; i < 5; i++)
|
|
701
|
+
{
|
|
702
|
+
if (malloc_failed(values[i]))
|
|
703
|
+
{
|
|
704
|
+
pool_error("pool_query_cache_register: malloc() failed");
|
|
705
|
+
free_query_cache_info();
|
|
706
|
+
{
|
|
707
|
+
int j;
|
|
708
|
+
for (j = 0; j < i; j++)
|
|
709
|
+
free(values[j]);
|
|
710
|
+
}
|
|
711
|
+
return -1;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
values_len[i] = strlen(values[i]);
|
|
715
|
+
}
|
|
716
|
+
values_format[0] = values_format[1] = values_format[3] = values_format[4] = 0;
|
|
717
|
+
values_format[2] = 1;
|
|
718
|
+
values_len[2] = query_cache_info->cache_offset;
|
|
719
|
+
|
|
720
|
+
pg_result = PQexecPrepared(system_db_info->pgconn,
|
|
721
|
+
CACHE_TABLE_INFO.register_prepared_statement,
|
|
722
|
+
5,
|
|
723
|
+
(const char * const *)values,
|
|
724
|
+
values_len,
|
|
725
|
+
values_format,
|
|
726
|
+
0);
|
|
727
|
+
if (!pg_result || PQresultStatus(pg_result) != PGRES_COMMAND_OK)
|
|
728
|
+
{
|
|
729
|
+
pool_error("pool_query_cache_register: PQexecPrepared() failed. reason: %s",
|
|
730
|
+
PQerrorMessage(system_db_info->pgconn));
|
|
731
|
+
|
|
732
|
+
PQclear(pg_result);
|
|
733
|
+
PQfreemem(escaped_query);
|
|
734
|
+
free_query_cache_info();
|
|
735
|
+
for (i = 0; i < 5; i++)
|
|
736
|
+
free(values[i]);
|
|
737
|
+
return -1;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
PQclear(pg_result);
|
|
741
|
+
PQfreemem(escaped_query);
|
|
742
|
+
for (i = 0; i < 5; i++)
|
|
743
|
+
free(values[i]);
|
|
744
|
+
free_query_cache_info();
|
|
745
|
+
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
case 'E':
|
|
750
|
+
{
|
|
751
|
+
pool_debug("pool_query_cache_register: received 'E': free query cache buffer");
|
|
752
|
+
|
|
753
|
+
pool_close_libpq_connection();
|
|
754
|
+
free_query_cache_info();
|
|
755
|
+
|
|
756
|
+
break;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
return 0;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/* --------------------------------
|
|
764
|
+
* init_query_cache_info() - allocate memory for query_cache_info and stores query
|
|
765
|
+
*
|
|
766
|
+
* returns 0 on success, -1 otherwise
|
|
767
|
+
`* --------------------------------
|
|
768
|
+
*/
|
|
769
|
+
static int
|
|
770
|
+
init_query_cache_info(POOL_CONNECTION *pc, char *database, char *query)
|
|
771
|
+
{
|
|
772
|
+
int query_len; /* length of the SELECT query to be cached */
|
|
773
|
+
|
|
774
|
+
query_cache_info = (QueryCacheInfo *)malloc(sizeof(QueryCacheInfo));
|
|
775
|
+
if (malloc_failed(query_cache_info))
|
|
776
|
+
return -1;
|
|
777
|
+
|
|
778
|
+
/* query */
|
|
779
|
+
query_len = strlen(query);
|
|
780
|
+
query_cache_info->query = (char *)malloc(query_len + 1);
|
|
781
|
+
if (malloc_failed(query_cache_info->query))
|
|
782
|
+
return -1;
|
|
783
|
+
memcpy(query_cache_info->query, query, query_len + 1);
|
|
784
|
+
|
|
785
|
+
/* md5_query */
|
|
786
|
+
query_cache_info->md5_query = (char *)malloc(33); /* md5sum is always 33 bytes (including the '\0') */
|
|
787
|
+
if (malloc_failed(query_cache_info->md5_query))
|
|
788
|
+
return -1;
|
|
789
|
+
pool_md5_hash(query_cache_info->query, query_len, query_cache_info->md5_query);
|
|
790
|
+
|
|
791
|
+
/* malloc DEFAULT_CACHE_SIZE for query_cache_info->cache */
|
|
792
|
+
query_cache_info->cache = (char *)malloc(DEFAULT_CACHE_SIZE);
|
|
793
|
+
if (malloc_failed(query_cache_info->cache))
|
|
794
|
+
return -1;
|
|
795
|
+
query_cache_info->cache_size = DEFAULT_CACHE_SIZE;
|
|
796
|
+
query_cache_info->cache_offset = 0;
|
|
797
|
+
|
|
798
|
+
/* save database name */
|
|
799
|
+
query_cache_info->db_name = (char *)malloc(strlen(database)+1);
|
|
800
|
+
if (malloc_failed(query_cache_info->db_name))
|
|
801
|
+
return -1;
|
|
802
|
+
strcpy(query_cache_info->db_name, database);
|
|
803
|
+
|
|
804
|
+
/* initialize create_timestamp */
|
|
805
|
+
query_cache_info->create_time = NULL;
|
|
806
|
+
|
|
807
|
+
return 0;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
/* --------------------------------
|
|
811
|
+
* free_query_cache_info() - free query_cache_info and its members
|
|
812
|
+
* --------------------------------
|
|
813
|
+
*/
|
|
814
|
+
static void
|
|
815
|
+
free_query_cache_info(void)
|
|
816
|
+
{
|
|
817
|
+
if (query_cache_info == NULL)
|
|
818
|
+
return;
|
|
819
|
+
|
|
820
|
+
free(query_cache_info->md5_query);
|
|
821
|
+
free(query_cache_info->query);
|
|
822
|
+
free(query_cache_info->cache);
|
|
823
|
+
free(query_cache_info->db_name);
|
|
824
|
+
if (query_cache_info->create_time)
|
|
825
|
+
free(query_cache_info->create_time);
|
|
826
|
+
free(query_cache_info);
|
|
827
|
+
query_cache_info = NULL;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/* --------------------------------
|
|
831
|
+
* malloc_failed() - checks if the caller's most recent malloc() has succeeded
|
|
832
|
+
*
|
|
833
|
+
* returns 0 if malloc() was a success, -1 otherwise
|
|
834
|
+
`* --------------------------------
|
|
835
|
+
*/
|
|
836
|
+
static int
|
|
837
|
+
malloc_failed(void *p)
|
|
838
|
+
{
|
|
839
|
+
if (p != NULL)
|
|
840
|
+
return 0;
|
|
841
|
+
|
|
842
|
+
pool_error("pool_query_cache: malloc() failed");
|
|
843
|
+
free_query_cache_info();
|
|
844
|
+
|
|
845
|
+
return -1;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/* --------------------------------
|
|
849
|
+
* write_cache() - append result data to buffer
|
|
850
|
+
*
|
|
851
|
+
* returns 0 on success, -1 otherwise
|
|
852
|
+
* --------------------------------
|
|
853
|
+
*/
|
|
854
|
+
static int
|
|
855
|
+
write_cache(void *buf, int len)
|
|
856
|
+
{
|
|
857
|
+
int required_len;
|
|
858
|
+
|
|
859
|
+
if (len < 0)
|
|
860
|
+
return -1;
|
|
861
|
+
|
|
862
|
+
required_len = query_cache_info->cache_offset + len;
|
|
863
|
+
if (required_len > query_cache_info->cache_size)
|
|
864
|
+
{
|
|
865
|
+
char *ptr;
|
|
866
|
+
|
|
867
|
+
required_len = query_cache_info->cache_size * 2;
|
|
868
|
+
ptr = (char *)realloc(query_cache_info->cache, required_len);
|
|
869
|
+
if (malloc_failed(ptr))
|
|
870
|
+
return -1;
|
|
871
|
+
|
|
872
|
+
query_cache_info->cache = ptr;
|
|
873
|
+
query_cache_info->cache_size = required_len;
|
|
874
|
+
|
|
875
|
+
pool_debug("pool_query_cache: extended cache buffer size to %d", query_cache_info->cache_size);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
memcpy(query_cache_info->cache + query_cache_info->cache_offset, buf, len);
|
|
879
|
+
query_cache_info->cache_offset += len;
|
|
880
|
+
|
|
881
|
+
return 0;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/* --------------------------------
|
|
885
|
+
* pq_time_to_str() - convert time_t to ISO standard time output string
|
|
886
|
+
*
|
|
887
|
+
* returns a pointer to newly allocated string, NULL if malloc fails
|
|
888
|
+
* --------------------------------
|
|
889
|
+
*/
|
|
890
|
+
static char *
|
|
891
|
+
pq_time_to_str(time_t t)
|
|
892
|
+
{
|
|
893
|
+
char *time_p;
|
|
894
|
+
char iso_time[32];
|
|
895
|
+
struct tm *tm;
|
|
896
|
+
|
|
897
|
+
tm = localtime(&t);
|
|
898
|
+
strftime(iso_time, sizeof(iso_time), "%Y-%m-%d %H:%M:%S%z", tm);
|
|
899
|
+
|
|
900
|
+
time_p = strdup(iso_time);
|
|
901
|
+
|
|
902
|
+
return time_p;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
/* --------------------------------
|
|
907
|
+
* system_db_connection_exists() - checks and if a connection to the SystemDB exists
|
|
908
|
+
*
|
|
909
|
+
* if not connected, it makes an attempt to connect to the SystemDB. If a connection
|
|
910
|
+
* exists, returns 1, returns 0 otherwise.
|
|
911
|
+
* --------------------------------
|
|
912
|
+
*/
|
|
913
|
+
static int
|
|
914
|
+
system_db_connection_exists(void)
|
|
915
|
+
{
|
|
916
|
+
if (!system_db_info->pgconn ||
|
|
917
|
+
(PQstatus(system_db_info->pgconn) != CONNECTION_OK))
|
|
918
|
+
{
|
|
919
|
+
if (system_db_connect())
|
|
920
|
+
return 0;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
return 1;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
/* --------------------------------
|
|
928
|
+
* define_prepared_statements() - defines prepared statements for the current session
|
|
929
|
+
* --------------------------------
|
|
930
|
+
*/
|
|
931
|
+
static void
|
|
932
|
+
define_prepared_statements(void)
|
|
933
|
+
{
|
|
934
|
+
PGresult *pg_result;
|
|
935
|
+
char *sql = NULL;
|
|
936
|
+
int sql_len;
|
|
937
|
+
|
|
938
|
+
sql_len =
|
|
939
|
+
strlen(pool_config->system_db_schema) +
|
|
940
|
+
strlen(QUERY_CACHE_TABLE_NAME) +
|
|
941
|
+
1024;
|
|
942
|
+
|
|
943
|
+
sql = (char *)malloc(sql_len);
|
|
944
|
+
if (malloc_failed(sql))
|
|
945
|
+
{
|
|
946
|
+
pool_error("pool_query_cache: malloc() failed");
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
free(CACHE_TABLE_INFO.register_prepared_statement);
|
|
951
|
+
CACHE_TABLE_INFO.register_prepared_statement
|
|
952
|
+
= strdup(CACHE_REGISTER_PREPARED_STMT);
|
|
953
|
+
if (malloc_failed(CACHE_TABLE_INFO.register_prepared_statement))
|
|
954
|
+
{
|
|
955
|
+
pool_error("pool_query_cache: malloc() failed");
|
|
956
|
+
free(sql);
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
#ifdef HAVE_PQPREPARE
|
|
961
|
+
snprintf(sql, sql_len,
|
|
962
|
+
"INSERT INTO %s.%s VALUES ( $1, $2, $3, $4, $5 )",
|
|
963
|
+
pool_config->system_db_schema,
|
|
964
|
+
QUERY_CACHE_TABLE_NAME);
|
|
965
|
+
pg_result = PQprepare(system_db_info->pgconn,
|
|
966
|
+
CACHE_TABLE_INFO.register_prepared_statement,
|
|
967
|
+
sql,
|
|
968
|
+
5,
|
|
969
|
+
NULL);
|
|
970
|
+
#else
|
|
971
|
+
snprintf(sql, sql_len,
|
|
972
|
+
"PREPARE %s (TEXT, TEXT, BYTEA, TEXT, TIMESTAMP WITH TIME ZONE) AS INSERT INTO %s.%s VALUES ( $1, $2, $3, $4, $5 )",
|
|
973
|
+
CACHE_TABLE_INFO.register_prepared_statement,
|
|
974
|
+
pool_config->system_db_schema,
|
|
975
|
+
QUERY_CACHE_TABLE_NAME);
|
|
976
|
+
pg_result = PQexec(system_db_info->pgconn, sql);
|
|
977
|
+
#endif
|
|
978
|
+
if (!pg_result || PQresultStatus(pg_result) != PGRES_COMMAND_OK)
|
|
979
|
+
{
|
|
980
|
+
pool_error("pool_query_cache: PQprepare() failed: %s", PQerrorMessage(system_db_info->pgconn));
|
|
981
|
+
free(CACHE_TABLE_INFO.register_prepared_statement);
|
|
982
|
+
free(sql);
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
pool_debug("pool_query_cache: prepared statements created");
|
|
987
|
+
CACHE_TABLE_INFO.has_prepared_statement = 1;
|
|
988
|
+
|
|
989
|
+
free(sql);
|
|
990
|
+
PQclear(pg_result);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/* --------------------------------
|
|
994
|
+
* Execute query cache look up
|
|
995
|
+
* --------------------------------
|
|
996
|
+
*/
|
|
997
|
+
POOL_STATUS pool_execute_query_cache_lookup(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, Node *node)
|
|
998
|
+
{
|
|
999
|
+
SelectStmt *select = (SelectStmt *)node;
|
|
1000
|
+
POOL_STATUS status = POOL_END; /* cache not found */
|
|
1001
|
+
|
|
1002
|
+
if (! (select->intoClause || select->lockingClause))
|
|
1003
|
+
{
|
|
1004
|
+
parsed_query = strdup(nodeToString(node));
|
|
1005
|
+
if (parsed_query == NULL)
|
|
1006
|
+
{
|
|
1007
|
+
pool_error("pool_execute_query_cache_lookup: malloc failed");
|
|
1008
|
+
return POOL_ERROR;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
status = pool_query_cache_lookup(frontend, parsed_query, backend->info->database, TSTATE(backend, MASTER_NODE_ID));
|
|
1012
|
+
if (status == POOL_CONTINUE)
|
|
1013
|
+
{
|
|
1014
|
+
free(parsed_query);
|
|
1015
|
+
parsed_query = NULL;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
return status;
|
|
1020
|
+
}
|