v3 ea843d1560a4 cached
543 files
5.1 MB
1.4M tokens
384 symbols
1 requests
Download .txt
Showing preview only (5,457K chars total). Download the full file or copy to clipboard to get everything.
Repository: kevinoid/postgresql-for-wordpress
Branch: v3
Commit: ea843d1560a4
Files: 543
Total size: 5.1 MB

Directory structure:
gitextract_y00m6hv_/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── sql-rewriting-issue.md
│   ├── pull_request_template.md
│   └── workflows/
│       └── php.yml
├── .gitignore
├── license.md
├── pg4wp/
│   ├── core.php
│   ├── db.php
│   ├── driver_mysql.php
│   ├── driver_pgsql.php
│   ├── driver_pgsql_rewrite.php
│   └── rewriters/
│       ├── AbstractSQLRewriter.php
│       ├── AlterTableSQLRewriter.php
│       ├── CreateTableSQLRewriter.php
│       ├── DeleteSQLRewriter.php
│       ├── DescribeSQLRewriter.php
│       ├── DropTableSQLRewriter.php
│       ├── InsertSQLRewriter.php
│       ├── OptimizeTableSQLRewriter.php
│       ├── ReplaceIntoSQLRewriter.php
│       ├── SelectSQLRewriter.php
│       ├── SetNamesSQLRewriter.php
│       ├── ShowFullColumnsSQLRewriter.php
│       ├── ShowIndexSQLRewriter.php
│       ├── ShowTableStatusSQLRewriter.php
│       ├── ShowTablesSQLRewriter.php
│       ├── ShowVariablesSQLRewriter.php
│       └── UpdateSQLRewriter.php
├── phpunit.xml
├── readme.md
├── tests/
│   ├── parseTest.php
│   ├── rewriteTest.php
│   ├── stubs/
│   │   ├── delete-fro_1698679875.txt
│   │   ├── delete-fro_1698679877.txt
│   │   ├── delete-fro_1698679878.txt
│   │   ├── delete-fro_1698679918.txt
│   │   ├── delete-fro_1698679920.txt
│   │   ├── delete-fro_1698679954.txt
│   │   ├── delete-fro_1698679955.txt
│   │   ├── insert-int_1698679874.txt
│   │   ├── insert-int_1698679877.txt
│   │   ├── insert-int_1698679878.txt
│   │   ├── insert-int_1698679884.txt
│   │   ├── insert-int_1698679897.txt
│   │   ├── insert-int_1698679908.txt
│   │   ├── insert-int_1698679917.txt
│   │   ├── insert-int_1698679920.txt
│   │   ├── insert-int_1698679923.txt
│   │   ├── insert-int_1698679936.txt
│   │   ├── insert-int_1698679954.txt
│   │   ├── insert-int_1698679955.txt
│   │   ├── insert-int_1698679965.txt
│   │   ├── insert-int_1698679972.txt
│   │   ├── select-aut_1698679874.txt
│   │   ├── select-aut_1698679884.txt
│   │   ├── select-aut_1698679897.txt
│   │   ├── select-aut_1698679908.txt
│   │   ├── select-aut_1698679917.txt
│   │   ├── select-aut_1698679923.txt
│   │   ├── select-aut_1698679965.txt
│   │   ├── select-aut_1698679972.txt
│   │   ├── select-blo_1698679989.txt
│   │   ├── select-com_1698679872.txt
│   │   ├── select-com_1698679886.txt
│   │   ├── select-com_1698679936.txt
│   │   ├── select-cou_1698679872.txt
│   │   ├── select-cou_1698679874.txt
│   │   ├── select-cou_1698679884.txt
│   │   ├── select-cou_1698679886.txt
│   │   ├── select-cou_1698679889.txt
│   │   ├── select-cou_1698679900.txt
│   │   ├── select-cou_1698679910.txt
│   │   ├── select-cou_1698679917.txt
│   │   ├── select-cou_1698679926.txt
│   │   ├── select-cou_1698679929.txt
│   │   ├── select-cou_1698679931.txt
│   │   ├── select-cou_1698679936.txt
│   │   ├── select-cou_1698679941.txt
│   │   ├── select-cou_1698679949.txt
│   │   ├── select-cou_1698679952.txt
│   │   ├── select-cou_1698679955.txt
│   │   ├── select-cou_1698679965.txt
│   │   ├── select-cou_1698679972.txt
│   │   ├── select-cou_1698679984.txt
│   │   ├── select-dis_1698679872.txt
│   │   ├── select-dis_1698679874.txt
│   │   ├── select-dis_1698679876.txt
│   │   ├── select-dis_1698679884.txt
│   │   ├── select-dis_1698679885.txt
│   │   ├── select-dis_1698679886.txt
│   │   ├── select-dis_1698679910.txt
│   │   ├── select-dis_1698679917.txt
│   │   ├── select-dis_1698679929.txt
│   │   ├── select-dis_1698679931.txt
│   │   ├── select-dis_1698679936.txt
│   │   ├── select-dis_1698679941.txt
│   │   ├── select-dis_1698679949.txt
│   │   ├── select-dis_1698679952.txt
│   │   ├── select-dis_1698679955.txt
│   │   ├── select-dis_1698679965.txt
│   │   ├── select-dis_1698679972.txt
│   │   ├── select-dis_1698679984.txt
│   │   ├── select-fro_1698679872.txt
│   │   ├── select-fro_1698679873.txt
│   │   ├── select-fro_1698679874.txt
│   │   ├── select-fro_1698679875.txt
│   │   ├── select-fro_1698679876.txt
│   │   ├── select-fro_1698679883.txt
│   │   ├── select-fro_1698679884.txt
│   │   ├── select-fro_1698679886.txt
│   │   ├── select-fro_1698679887.txt
│   │   ├── select-fro_1698679889.txt
│   │   ├── select-fro_1698679897.txt
│   │   ├── select-fro_1698679900.txt
│   │   ├── select-fro_1698679907.txt
│   │   ├── select-fro_1698679910.txt
│   │   ├── select-fro_1698679911.txt
│   │   ├── select-fro_1698679917.txt
│   │   ├── select-fro_1698679918.txt
│   │   ├── select-fro_1698679919.txt
│   │   ├── select-fro_1698679922.txt
│   │   ├── select-fro_1698679923.txt
│   │   ├── select-fro_1698679924.txt
│   │   ├── select-fro_1698679926.txt
│   │   ├── select-fro_1698679929.txt
│   │   ├── select-fro_1698679931.txt
│   │   ├── select-fro_1698679935.txt
│   │   ├── select-fro_1698679936.txt
│   │   ├── select-fro_1698679940.txt
│   │   ├── select-fro_1698679941.txt
│   │   ├── select-fro_1698679949.txt
│   │   ├── select-fro_1698679950.txt
│   │   ├── select-fro_1698679952.txt
│   │   ├── select-fro_1698679954.txt
│   │   ├── select-fro_1698679955.txt
│   │   ├── select-fro_1698679956.txt
│   │   ├── select-fro_1698679960.txt
│   │   ├── select-fro_1698679965.txt
│   │   ├── select-fro_1698679972.txt
│   │   ├── select-fro_1698679984.txt
│   │   ├── select-fro_1698679985.txt
│   │   ├── select-fro_1698679987.txt
│   │   ├── select-fro_1698679988.txt
│   │   ├── select-fro_1698679989.txt
│   │   ├── select-fro_1698679991.txt
│   │   ├── select-fro_1698679992.txt
│   │   ├── select-fro_1698679996.txt
│   │   ├── select-fro_1698679999.txt
│   │   ├── select-fro_1698680063.txt
│   │   ├── select-fro_1698680183.txt
│   │   ├── select-fro_1698680305.txt
│   │   ├── select-id-_1698679924.txt
│   │   ├── select-id-_1698679926.txt
│   │   ├── select-met_1698679872.txt
│   │   ├── select-met_1698679874.txt
│   │   ├── select-met_1698679875.txt
│   │   ├── select-met_1698679876.txt
│   │   ├── select-met_1698679877.txt
│   │   ├── select-met_1698679878.txt
│   │   ├── select-met_1698679883.txt
│   │   ├── select-met_1698679884.txt
│   │   ├── select-met_1698679886.txt
│   │   ├── select-met_1698679887.txt
│   │   ├── select-met_1698679889.txt
│   │   ├── select-met_1698679897.txt
│   │   ├── select-met_1698679900.txt
│   │   ├── select-met_1698679907.txt
│   │   ├── select-met_1698679908.txt
│   │   ├── select-met_1698679910.txt
│   │   ├── select-met_1698679911.txt
│   │   ├── select-met_1698679917.txt
│   │   ├── select-met_1698679918.txt
│   │   ├── select-met_1698679919.txt
│   │   ├── select-met_1698679920.txt
│   │   ├── select-met_1698679922.txt
│   │   ├── select-met_1698679923.txt
│   │   ├── select-met_1698679924.txt
│   │   ├── select-met_1698679926.txt
│   │   ├── select-met_1698679929.txt
│   │   ├── select-met_1698679931.txt
│   │   ├── select-met_1698679935.txt
│   │   ├── select-met_1698679936.txt
│   │   ├── select-met_1698679940.txt
│   │   ├── select-met_1698679949.txt
│   │   ├── select-met_1698679950.txt
│   │   ├── select-met_1698679952.txt
│   │   ├── select-met_1698679954.txt
│   │   ├── select-met_1698679955.txt
│   │   ├── select-met_1698679956.txt
│   │   ├── select-met_1698679960.txt
│   │   ├── select-met_1698679965.txt
│   │   ├── select-met_1698679972.txt
│   │   ├── select-met_1698679984.txt
│   │   ├── select-met_1698679985.txt
│   │   ├── select-met_1698679987.txt
│   │   ├── select-met_1698679988.txt
│   │   ├── select-met_1698679989.txt
│   │   ├── select-met_1698679991.txt
│   │   ├── select-met_1698679992.txt
│   │   ├── select-met_1698679993.txt
│   │   ├── select-met_1698679996.txt
│   │   ├── select-met_1698679999.txt
│   │   ├── select-met_1698680063.txt
│   │   ├── select-met_1698680183.txt
│   │   ├── select-met_1698680305.txt
│   │   ├── select-opt_1698679872.txt
│   │   ├── select-opt_1698679874.txt
│   │   ├── select-opt_1698679875.txt
│   │   ├── select-opt_1698679876.txt
│   │   ├── select-opt_1698679883.txt
│   │   ├── select-opt_1698679884.txt
│   │   ├── select-opt_1698679886.txt
│   │   ├── select-opt_1698679887.txt
│   │   ├── select-opt_1698679889.txt
│   │   ├── select-opt_1698679897.txt
│   │   ├── select-opt_1698679900.txt
│   │   ├── select-opt_1698679907.txt
│   │   ├── select-opt_1698679908.txt
│   │   ├── select-opt_1698679910.txt
│   │   ├── select-opt_1698679911.txt
│   │   ├── select-opt_1698679917.txt
│   │   ├── select-opt_1698679918.txt
│   │   ├── select-opt_1698679919.txt
│   │   ├── select-opt_1698679922.txt
│   │   ├── select-opt_1698679923.txt
│   │   ├── select-opt_1698679924.txt
│   │   ├── select-opt_1698679926.txt
│   │   ├── select-opt_1698679929.txt
│   │   ├── select-opt_1698679931.txt
│   │   ├── select-opt_1698679935.txt
│   │   ├── select-opt_1698679936.txt
│   │   ├── select-opt_1698679940.txt
│   │   ├── select-opt_1698679941.txt
│   │   ├── select-opt_1698679949.txt
│   │   ├── select-opt_1698679950.txt
│   │   ├── select-opt_1698679952.txt
│   │   ├── select-opt_1698679954.txt
│   │   ├── select-opt_1698679955.txt
│   │   ├── select-opt_1698679956.txt
│   │   ├── select-opt_1698679960.txt
│   │   ├── select-opt_1698679965.txt
│   │   ├── select-opt_1698679972.txt
│   │   ├── select-opt_1698679984.txt
│   │   ├── select-opt_1698679985.txt
│   │   ├── select-opt_1698679987.txt
│   │   ├── select-opt_1698679988.txt
│   │   ├── select-opt_1698679989.txt
│   │   ├── select-opt_1698679991.txt
│   │   ├── select-opt_1698679992.txt
│   │   ├── select-opt_1698679993.txt
│   │   ├── select-opt_1698679996.txt
│   │   ├── select-opt_1698679999.txt
│   │   ├── select-opt_1698680063.txt
│   │   ├── select-opt_1698680183.txt
│   │   ├── select-opt_1698680305.txt
│   │   ├── select-pos_1698679872.txt
│   │   ├── select-pos_1698679873.txt
│   │   ├── select-pos_1698679874.txt
│   │   ├── select-pos_1698679876.txt
│   │   ├── select-pos_1698679884.txt
│   │   ├── select-pos_1698679885.txt
│   │   ├── select-pos_1698679886.txt
│   │   ├── select-pos_1698679887.txt
│   │   ├── select-pos_1698679910.txt
│   │   ├── select-pos_1698679911.txt
│   │   ├── select-pos_1698679917.txt
│   │   ├── select-pos_1698679919.txt
│   │   ├── select-pos_1698679923.txt
│   │   ├── select-pos_1698679924.txt
│   │   ├── select-pos_1698679926.txt
│   │   ├── select-pos_1698679929.txt
│   │   ├── select-pos_1698679931.txt
│   │   ├── select-pos_1698679936.txt
│   │   ├── select-pos_1698679941.txt
│   │   ├── select-pos_1698679949.txt
│   │   ├── select-pos_1698679952.txt
│   │   ├── select-pos_1698679955.txt
│   │   ├── select-pos_1698679956.txt
│   │   ├── select-pos_1698679965.txt
│   │   ├── select-pos_1698679972.txt
│   │   ├── select-pos_1698679984.txt
│   │   ├── select-ses_1698679872.txt
│   │   ├── select-ses_1698679874.txt
│   │   ├── select-ses_1698679875.txt
│   │   ├── select-ses_1698679876.txt
│   │   ├── select-ses_1698679883.txt
│   │   ├── select-ses_1698679884.txt
│   │   ├── select-ses_1698679886.txt
│   │   ├── select-ses_1698679887.txt
│   │   ├── select-ses_1698679889.txt
│   │   ├── select-ses_1698679897.txt
│   │   ├── select-ses_1698679900.txt
│   │   ├── select-ses_1698679907.txt
│   │   ├── select-ses_1698679910.txt
│   │   ├── select-ses_1698679911.txt
│   │   ├── select-ses_1698679917.txt
│   │   ├── select-ses_1698679918.txt
│   │   ├── select-ses_1698679919.txt
│   │   ├── select-ses_1698679922.txt
│   │   ├── select-ses_1698679923.txt
│   │   ├── select-ses_1698679924.txt
│   │   ├── select-ses_1698679926.txt
│   │   ├── select-ses_1698679928.txt
│   │   ├── select-ses_1698679931.txt
│   │   ├── select-ses_1698679935.txt
│   │   ├── select-ses_1698679936.txt
│   │   ├── select-ses_1698679940.txt
│   │   ├── select-ses_1698679949.txt
│   │   ├── select-ses_1698679950.txt
│   │   ├── select-ses_1698679952.txt
│   │   ├── select-ses_1698679953.txt
│   │   ├── select-ses_1698679954.txt
│   │   ├── select-ses_1698679955.txt
│   │   ├── select-ses_1698679956.txt
│   │   ├── select-ses_1698679960.txt
│   │   ├── select-ses_1698679965.txt
│   │   ├── select-ses_1698679972.txt
│   │   ├── select-ses_1698679984.txt
│   │   ├── select-ses_1698679985.txt
│   │   ├── select-ses_1698679987.txt
│   │   ├── select-ses_1698679988.txt
│   │   ├── select-ses_1698679989.txt
│   │   ├── select-ses_1698679991.txt
│   │   ├── select-ses_1698679992.txt
│   │   ├── select-ses_1698679995.txt
│   │   ├── select-ses_1698679999.txt
│   │   ├── select-ses_1698680063.txt
│   │   ├── select-ses_1698680183.txt
│   │   ├── select-ses_1698680304.txt
│   │   ├── select-sql_1698679872.txt
│   │   ├── select-sql_1698679874.txt
│   │   ├── select-sql_1698679875.txt
│   │   ├── select-sql_1698679876.txt
│   │   ├── select-sql_1698679884.txt
│   │   ├── select-sql_1698679886.txt
│   │   ├── select-sql_1698679917.txt
│   │   ├── select-sql_1698679918.txt
│   │   ├── select-sql_1698679919.txt
│   │   ├── select-sql_1698679923.txt
│   │   ├── select-sql_1698679929.txt
│   │   ├── select-sql_1698679931.txt
│   │   ├── select-sql_1698679936.txt
│   │   ├── select-sql_1698679941.txt
│   │   ├── select-sql_1698679952.txt
│   │   ├── select-sql_1698679954.txt
│   │   ├── select-sql_1698679955.txt
│   │   ├── select-sql_1698679956.txt
│   │   ├── select-sql_1698679989.txt
│   │   ├── select-sql_1698679991.txt
│   │   ├── select-t-t_1698679872.txt
│   │   ├── select-t-t_1698679874.txt
│   │   ├── select-t-t_1698679875.txt
│   │   ├── select-t-t_1698679876.txt
│   │   ├── select-t-t_1698679883.txt
│   │   ├── select-t-t_1698679884.txt
│   │   ├── select-t-t_1698679886.txt
│   │   ├── select-t-t_1698679887.txt
│   │   ├── select-t-t_1698679889.txt
│   │   ├── select-t-t_1698679897.txt
│   │   ├── select-t-t_1698679900.txt
│   │   ├── select-t-t_1698679907.txt
│   │   ├── select-t-t_1698679908.txt
│   │   ├── select-t-t_1698679910.txt
│   │   ├── select-t-t_1698679911.txt
│   │   ├── select-t-t_1698679917.txt
│   │   ├── select-t-t_1698679918.txt
│   │   ├── select-t-t_1698679919.txt
│   │   ├── select-t-t_1698679922.txt
│   │   ├── select-t-t_1698679923.txt
│   │   ├── select-t-t_1698679924.txt
│   │   ├── select-t-t_1698679926.txt
│   │   ├── select-t-t_1698679929.txt
│   │   ├── select-t-t_1698679931.txt
│   │   ├── select-t-t_1698679936.txt
│   │   ├── select-t-t_1698679941.txt
│   │   ├── select-t-t_1698679949.txt
│   │   ├── select-t-t_1698679950.txt
│   │   ├── select-t-t_1698679952.txt
│   │   ├── select-t-t_1698679954.txt
│   │   ├── select-t-t_1698679955.txt
│   │   ├── select-t-t_1698679956.txt
│   │   ├── select-t-t_1698679960.txt
│   │   ├── select-t-t_1698679965.txt
│   │   ├── select-t-t_1698679972.txt
│   │   ├── select-t-t_1698679984.txt
│   │   ├── select-t-t_1698679985.txt
│   │   ├── select-t-t_1698679987.txt
│   │   ├── select-t-t_1698679988.txt
│   │   ├── select-t-t_1698679989.txt
│   │   ├── select-t-t_1698679991.txt
│   │   ├── select-t-t_1698679992.txt
│   │   ├── select-t-t_1698679996.txt
│   │   ├── select-t-t_1698679999.txt
│   │   ├── select-t-t_1698680063.txt
│   │   ├── select-t-t_1698680183.txt
│   │   ├── select-t-t_1698680305.txt
│   │   ├── select-ter_1698679965.txt
│   │   ├── select-ter_1698679972.txt
│   │   ├── select-tt-_1698679897.txt
│   │   ├── select-tt-_1698679908.txt
│   │   ├── select-use_1698679872.txt
│   │   ├── select-use_1698679874.txt
│   │   ├── select-use_1698679875.txt
│   │   ├── select-use_1698679876.txt
│   │   ├── select-use_1698679883.txt
│   │   ├── select-use_1698679884.txt
│   │   ├── select-use_1698679886.txt
│   │   ├── select-use_1698679887.txt
│   │   ├── select-use_1698679889.txt
│   │   ├── select-use_1698679897.txt
│   │   ├── select-use_1698679900.txt
│   │   ├── select-use_1698679907.txt
│   │   ├── select-use_1698679910.txt
│   │   ├── select-use_1698679911.txt
│   │   ├── select-use_1698679917.txt
│   │   ├── select-use_1698679918.txt
│   │   ├── select-use_1698679919.txt
│   │   ├── select-use_1698679922.txt
│   │   ├── select-use_1698679923.txt
│   │   ├── select-use_1698679924.txt
│   │   ├── select-use_1698679926.txt
│   │   ├── select-use_1698679929.txt
│   │   ├── select-use_1698679931.txt
│   │   ├── select-use_1698679936.txt
│   │   ├── select-use_1698679941.txt
│   │   ├── select-use_1698679949.txt
│   │   ├── select-use_1698679950.txt
│   │   ├── select-use_1698679952.txt
│   │   ├── select-use_1698679954.txt
│   │   ├── select-use_1698679955.txt
│   │   ├── select-use_1698679956.txt
│   │   ├── select-use_1698679960.txt
│   │   ├── select-use_1698679965.txt
│   │   ├── select-use_1698679972.txt
│   │   ├── select-use_1698679984.txt
│   │   ├── select-use_1698679985.txt
│   │   ├── select-use_1698679987.txt
│   │   ├── select-use_1698679988.txt
│   │   ├── select-use_1698679989.txt
│   │   ├── select-use_1698679991.txt
│   │   ├── select-use_1698679992.txt
│   │   ├── select-use_1698679996.txt
│   │   ├── select-use_1698679999.txt
│   │   ├── select-use_1698680063.txt
│   │   ├── select-use_1698680183.txt
│   │   ├── select-use_1698680305.txt
│   │   ├── select-wp-_1698679872.txt
│   │   ├── select-wp-_1698679875.txt
│   │   ├── select-wp-_1698679883.txt
│   │   ├── select-wp-_1698679884.txt
│   │   ├── select-wp-_1698679887.txt
│   │   ├── select-wp-_1698679889.txt
│   │   ├── select-wp-_1698679897.txt
│   │   ├── select-wp-_1698679900.txt
│   │   ├── select-wp-_1698679908.txt
│   │   ├── select-wp-_1698679911.txt
│   │   ├── select-wp-_1698679922.txt
│   │   ├── select-wp-_1698679950.txt
│   │   ├── select-wp-_1698679956.txt
│   │   ├── select-wp-_1698679960.txt
│   │   ├── select-wp-_1698679985.txt
│   │   ├── select-wp-_1698679988.txt
│   │   ├── select-wp-_1698680305.txt
│   │   ├── set-names-_1698679872.txt
│   │   ├── set-names-_1698679874.txt
│   │   ├── set-names-_1698679875.txt
│   │   ├── set-names-_1698679876.txt
│   │   ├── set-names-_1698679883.txt
│   │   ├── set-names-_1698679884.txt
│   │   ├── set-names-_1698679886.txt
│   │   ├── set-names-_1698679887.txt
│   │   ├── set-names-_1698679889.txt
│   │   ├── set-names-_1698679897.txt
│   │   ├── set-names-_1698679900.txt
│   │   ├── set-names-_1698679907.txt
│   │   ├── set-names-_1698679910.txt
│   │   ├── set-names-_1698679911.txt
│   │   ├── set-names-_1698679917.txt
│   │   ├── set-names-_1698679918.txt
│   │   ├── set-names-_1698679919.txt
│   │   ├── set-names-_1698679922.txt
│   │   ├── set-names-_1698679923.txt
│   │   ├── set-names-_1698679924.txt
│   │   ├── set-names-_1698679926.txt
│   │   ├── set-names-_1698679928.txt
│   │   ├── set-names-_1698679931.txt
│   │   ├── set-names-_1698679935.txt
│   │   ├── set-names-_1698679936.txt
│   │   ├── set-names-_1698679940.txt
│   │   ├── set-names-_1698679949.txt
│   │   ├── set-names-_1698679950.txt
│   │   ├── set-names-_1698679952.txt
│   │   ├── set-names-_1698679953.txt
│   │   ├── set-names-_1698679954.txt
│   │   ├── set-names-_1698679955.txt
│   │   ├── set-names-_1698679956.txt
│   │   ├── set-names-_1698679960.txt
│   │   ├── set-names-_1698679965.txt
│   │   ├── set-names-_1698679972.txt
│   │   ├── set-names-_1698679984.txt
│   │   ├── set-names-_1698679985.txt
│   │   ├── set-names-_1698679987.txt
│   │   ├── set-names-_1698679988.txt
│   │   ├── set-names-_1698679989.txt
│   │   ├── set-names-_1698679991.txt
│   │   ├── set-names-_1698679992.txt
│   │   ├── set-names-_1698679995.txt
│   │   ├── set-names-_1698679999.txt
│   │   ├── set-names-_1698680063.txt
│   │   ├── set-names-_1698680183.txt
│   │   ├── set-names-_1698680304.txt
│   │   ├── show-full-_1698679874.txt
│   │   ├── show-full-_1698679875.txt
│   │   ├── show-full-_1698679884.txt
│   │   ├── show-full-_1698679886.txt
│   │   ├── show-full-_1698679897.txt
│   │   ├── show-full-_1698679908.txt
│   │   ├── show-full-_1698679917.txt
│   │   ├── show-full-_1698679918.txt
│   │   ├── show-full-_1698679923.txt
│   │   ├── show-full-_1698679926.txt
│   │   ├── show-full-_1698679936.txt
│   │   ├── show-full-_1698679954.txt
│   │   ├── show-full-_1698679965.txt
│   │   ├── show-full-_1698679972.txt
│   │   ├── show-full-_1698679996.txt
│   │   ├── update-wp-_1698679874.txt
│   │   ├── update-wp-_1698679884.txt
│   │   ├── update-wp-_1698679886.txt
│   │   ├── update-wp-_1698679917.txt
│   │   ├── update-wp-_1698679923.txt
│   │   ├── update-wp-_1698679926.txt
│   │   ├── update-wp-_1698679936.txt
│   │   ├── update-wp-_1698679965.txt
│   │   ├── update-wp-_1698679972.txt
│   │   └── update-wp-_1698679996.txt
│   ├── tools/
│   │   ├── php-cs-fixer.phar
│   │   └── phpunit.phar
│   └── verifyAgainstStubsTest.php
└── wp-includes/
    ├── cache.php
    ├── class-wp-object-cache.php
    ├── class-wpdb.php
    ├── l10n.php
    └── version.php

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/sql-rewriting-issue.md
================================================
---
name: SQL Rewriting Issue
about: This is used for filing bugs or problems with PG4WP
title: ''
labels: ''
assignees: ''

---

WP Version:
PG4WP Version: 

Error: 
```

```

RAW SQL
```

```

Expected Rewritten SQL
```

```

Actual Rewritten SQL
```

```


================================================
FILE: .github/pull_request_template.md
================================================

Related Issues:
 - 

Added Tests:
 -

================================================
FILE: .github/workflows/php.yml
================================================
name: PHP Composer

on:
  push:
    branches: [ "v2", "v3" ]
  pull_request:
    branches: [ "v2", "v3" ]

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Run Tests
      run: ./tests/tools/phpunit.phar tests/

================================================
FILE: .gitignore
================================================
logs
.phpunit.result.cache
.php-cs-fixer.cache

================================================
FILE: license.md
================================================
# GNU GENERAL PUBLIC LICENSE

Version 2, June 1991

    Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

    Everyone is permitted to copy and distribute verbatim copies
    of this license document, but changing it is not allowed.

## Preamble

The licenses for most software are designed to take away your freedom
to share and change it. By contrast, the GNU General Public License is
intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.

We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on,
we want its recipients to know that what they have is not the
original, so that any problems introduced by others will not reflect
on the original authors' reputations.

Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at
all.

The precise terms and conditions for copying, distribution and
modification follow.

## TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

**0.** This License applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work
based on the Program" means either the Program or any derivative work
under copyright law: that is to say, a work containing the Program or
a portion of it, either verbatim or with modifications and/or
translated into another language. (Hereinafter, translation is
included without limitation in the term "modification".) Each licensee
is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the Program
(independent of having been made by running the Program). Whether that
is true depends on what the Program does.

**1.** You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a
fee.

**2.** You may modify your copy or copies of the Program or any
portion of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

  
**a)** You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.

  
**b)** You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any part
thereof, to be licensed as a whole at no charge to all third parties
under the terms of this License.

  
**c)** If the modified program normally reads commands interactively
when run, you must cause it, when started running for such interactive
use in the most ordinary way, to print or display an announcement
including an appropriate copyright notice and a notice that there is
no warranty (or else, saying that you provide a warranty) and that
users may redistribute the program under these conditions, and telling
the user how to view a copy of this License. (Exception: if the
Program itself is interactive but does not normally print such an
announcement, your work based on the Program is not required to print
an announcement.)

These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

**3.** You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

  
**a)** Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections 1
and 2 above on a medium customarily used for software interchange; or,

  
**b)** Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your cost of
physically performing source distribution, a complete machine-readable
copy of the corresponding source code, to be distributed under the
terms of Sections 1 and 2 above on a medium customarily used for
software interchange; or,

  
**c)** Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is allowed
only for noncommercial distribution and only if you received the
program in object code or executable form with such an offer, in
accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

**4.** You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt otherwise
to copy, modify, sublicense or distribute the Program is void, and
will automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.

**5.** You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

**6.** Each time you redistribute the Program (or any work based on
the Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

**7.** If, as a consequence of a court judgment or allegation of
patent infringement or for any other reason (not limited to patent
issues), conditions are imposed on you (whether by court order,
agreement or otherwise) that contradict the conditions of this
License, they do not excuse you from the conditions of this License.
If you cannot distribute so as to satisfy simultaneously your
obligations under this License and any other pertinent obligations,
then as a consequence you may not distribute the Program at all. For
example, if a patent license would not permit royalty-free
redistribution of the Program by all those who receive copies directly
or indirectly through you, then the only way you could satisfy both it
and this License would be to refrain entirely from distribution of the
Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

**8.** If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.

**9.** The Free Software Foundation may publish revised and/or new
versions of the General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Program does not specify a
version number of this License, you may choose any version ever
published by the Free Software Foundation.

**10.** If you wish to incorporate parts of the Program into other
free programs whose distribution conditions are different, write to
the author to ask for permission. For software which is copyrighted by
the Free Software Foundation, write to the Free Software Foundation;
we sometimes make exceptions for this. Our decision will be guided by
the two goals of preserving the free status of all derivatives of our
free software and of promoting the sharing and reuse of software
generally.

**NO WARRANTY**

**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

END OF TERMS AND CONDITIONS

## How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.

To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    one line to give the program's name and an idea of what it does.
    Copyright (C) yyyy  name of author

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

Also add information on how to contact you by electronic and paper
mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
    type `show w'.  This is free software, and you are welcome
    to redistribute it under certain conditions; type `show c' 
    for details.

The hypothetical commands \`show w' and \`show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than \`show w' and
\`show c'; they could even be mouse-clicks or menu items--whatever
suits your program.

You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the program,
if necessary. Here is a sample; alter the names:

    Yoyodyne, Inc., hereby disclaims all copyright
    interest in the program `Gnomovision'
    (which makes passes at compilers) written 
    by James Hacker.

    signature of Ty Coon, 1 April 1989
    Ty Coon, President of Vice

This General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library,
you may consider it more useful to permit linking proprietary
applications with the library. If this is what you want to do, use the
[GNU Lesser General Public
License](https://www.gnu.org/licenses/lgpl.html) instead of this
License.

================================================
FILE: pg4wp/core.php
================================================
<?php
/**
 * @package PostgreSQL_For_Wordpress
 * @version $Id$
 * @author	Hawk__, www.hawkix.net
 */

/**
* This file does all the initialisation tasks
*/

// This is required by class-wpdb so we must load it first
require_once ABSPATH . '/wp-includes/version.php';
require_once ABSPATH . '/wp-includes/cache.php';
require_once ABSPATH . '/wp-includes/l10n.php';

// Load the driver defined in 'db.php'
require_once(PG4WP_ROOT . '/driver_' . DB_DRIVER . '.php');

// This loads up the wpdb class applying appropriate changes to it
$replaces = array(
    'define( '	=> '// define( ',
    'class wpdb'	=> 'class wpdb2',
    'new wpdb'	=> 'new wpdb2',
    'instanceof mysqli_result' => 'instanceof \PgSql\Result',
    'instanceof mysqli' => 'instanceof \PgSql\Connection',
    '$this->dbh->connect_errno' => 'wpsqli_connect_error()',
    'mysqli_'	=> 'wpsqli_',
    'is_resource'	=> 'wpsqli_is_resource',
    '<?php'		=> '',
    '?>'		=> '',
);

eval(str_replace(array_keys($replaces), array_values($replaces), file_get_contents(ABSPATH . '/wp-includes/class-wpdb.php')));

// Create wpdb object if not already done
if (!isset($wpdb) && defined('DB_USER')) {
    $wpdb = new wpdb2(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
}


================================================
FILE: pg4wp/db.php
================================================
<?php
/*
Plugin Name: PostgreSQL for WordPress (PG4WP)
Plugin URI: https://github.com/PostgreSQL-For-Wordpress/postgresql-for-wordpress
Description: PG4WP is a special plugin enabling WordPress to use a PostgreSQL database.
Version: v3.0.0
Author: PostgreSQL-For-Wordpress
Author URI: https://github.com/PostgreSQL-For-Wordpress
License: GPLv2 or newer.
*/

// Ensure we only load this config once
if(!defined('PG4WP_ROOT')) {

    // You can choose the driver to load here
    if (!defined('DB_DRIVER')) {
        define('DB_DRIVER', 'pgsql');
    }

    // Set this to 'true' and check that `pg4wp` is writable if you want debug logs to be written
    if (!defined('PG4WP_DEBUG')) {
        define('PG4WP_DEBUG', false);
    }

    if (!defined('PG4WP_LOG_ERRORS')) {
        // If you just want to log queries that generate errors, leave PG4WP_DEBUG to "false"
        // and set this to true
        define('PG4WP_LOG_ERRORS', true);
    }

    // This defines the directory where PG4WP files are loaded from
    //   3 places checked : wp-content, wp-content/plugins and the base directory
    if(file_exists(ABSPATH . 'wp-content/pg4wp')) {
        define('PG4WP_ROOT', ABSPATH . 'wp-content/pg4wp');
    } elseif(file_exists(ABSPATH . 'wp-content/plugins/pg4wp')) {
        define('PG4WP_ROOT', ABSPATH . 'wp-content/plugins/pg4wp');
    } elseif(file_exists(ABSPATH . 'pg4wp')) {
        define('PG4WP_ROOT', ABSPATH . 'pg4wp');
    } else {
        die('PG4WP file directory not found');
    }

    // Logs are put in the pg4wp directory
    if (!defined('PG4WP_LOG')) {
        define('PG4WP_LOG', PG4WP_ROOT . '/logs/');
    }
    // Check if the logs directory is needed and exists or create it if possible
    if((PG4WP_DEBUG || PG4WP_LOG_ERRORS) && !file_exists(PG4WP_LOG) && is_writable(dirname(PG4WP_LOG))) {
        mkdir(PG4WP_LOG);
    }

    // Here happens all the magic
    require_once(PG4WP_ROOT . '/core.php');
} // Protection against multiple loading


================================================
FILE: pg4wp/driver_mysql.php
================================================
<?php

/**
* This file implements a mysql reference driver
* This driver should do nothing different vs a standard install
* This file remaps all wpsqli_* calls to mysqli_* original name
*/

/**
* Connection Handling
*/

/**
 * Initializes MySQLi and returns a resource for use with mysqli_real_connect().
 *
 * This function is a wrapper for the mysqli_init function, which initializes and returns
 * a resource for use with mysqli_real_connect(). It is part of the MySQLi extension's
 * object-oriented interface and is usually employed to prepare for a secure connection
 * using settings like mysqli_ssl_set() before establishing a connection to a MySQL server.
 * The function does not require any parameters and will return a mysqli object on success
 * or FALSE on failure.
 *
 * @return mysqli|false Returns an object which can be used with mysqli_real_connect() or
 *                      FALSE on failure.
 */
function wpsqli_init()
{
    return mysqli_init();
}

/**
 * Opens a connection to a mysql server in a real context.
 *
 * This function is a wrapper for the mysqli_real_connect function, which attempts to establish
 * a connection to a MySQL server. The function takes in parameters for the host name, username,
 * password, database name, port number, socket, and flags, all of which are optional except the
 * mysqli object returned by mysqli_init(). The flags parameter can be used to set different
 * connection options that can affect the behavior of the connection.
 *
 * @param mysqli $connection The mysqli object returned by mysqli_init().
 * @param string|null $hostname The host name or an IP address.
 * @param string|null $username The MySQL user name.
 * @param string|null $password The password associated with the username.
 * @param string|null $database The default database to be used when performing queries.
 * @param int|null $port The port number to attempt to connect to the MySQL server.
 * @param string|null $socket The socket or named pipe that should be used.
 * @param int $flags Client connection flags.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_real_connect($connection, $hostname = null, $username = null, $password = null, $database = null, $port = null, $socket = null, $flags = 0)
{
    return mysqli_real_connect($connection, $hostname, $username, $password, $database, $port, $socket, $flags);
}

/**
 * Closes a previously opened database connection.
 *
 * This function is a wrapper for the mysqli_close function. It is used to close a non-persistent
 * connection to a MySQL server that was opened with mysqli_connect() or mysqli_real_connect(). It's
 * important to close connections when they are no longer needed to free up resources on both the web
 * server and the MySQL server. The function returns TRUE on success or FALSE on failure.
 *
 * @param mysqli $connection The mysqli connection resource to be closed.
 * @return bool Returns TRUE on successful closure, FALSE on failure.
 */
function wpsqli_close($connection)
{
    return mysqli_close($connection);
}

/**
 * Used to establish secure connections using SSL.
 *
 * This function is a wrapper for the mysqli_ssl_set function. It is used to set the SSL
 * certificates and key files for establishing an encrypted connection between the client
 * and the MySQL server. This function should be called before mysqli_real_connect(). It's
 * important for security when the database server and the web server are on different hosts
 * or when sensitive data is being transferred.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param string $key The path to the key file.
 * @param string $cert The path to the certificate file.
 * @param string $ca The path to the certificate authority file.
 * @param string $capath The pathname to a directory that contains trusted SSL CA certificates
 *                       in PEM format.
 * @param string $cipher A list of allowable ciphers to use for SSL encryption.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_ssl_set($connection, $key, $cert, $ca, $capath, $cipher)
{
    return mysqli_ssl_set($connection, $key, $cert, $ca, $capath, $cipher);
}

/**
 * Returns the MySQL client library version as a string.
 *
 * This function is a wrapper for the mysqli_get_client_info function. It is used to retrieve
 * the version of the client library that is used to compile the MySQLi extension. The function
 * does not require any parameters and can be called statically. It is helpful for debugging
 * and ensuring that the PHP environment is using the correct version of the MySQL client library,
 * which can be important for compatibility and functionality reasons.
 *
 * @return string The MySQL client library version.
 */
function wpsqli_get_client_info()
{
    return mysqli_get_client_info();
}

/**
 * Retrieves the version of the MySQL server.
 *
 * This function is a wrapper for the mysqli_get_server_info function. It returns a string
 * representing the version of the MySQL server pointed to by the connection resource. This
 * information can be used for a variety of purposes, such as conditional behavior for different
 * MySQL versions or simply for logging and monitoring. Understanding the server version is
 * essential for ensuring compatibility with specific MySQL features and syntax.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return string The version of the MySQL server.
 */
function wpsqli_get_server_info($connection)
{
    return mysqli_get_server_info($connection);
}

/**
 * Returns a string representing the type of connection used.
 *
 * This function is a wrapper for the mysqli_get_host_info function. It retrieves information about
 * the type of connection that was established to the MySQL server and the host server information.
 * This includes the host name and the connection type, such as TCP/IP or a UNIX socket. It's useful
 * for debugging and for understanding how PHP is communicating with the MySQL server.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return string A string describing the connection type and server host information.
 */
function wpsqli_host_info($connection)
{
    return mysqli_get_host_info($connection);
}

/**
 * Pings a server connection, or tries to reconnect if the connection has gone down.
 *
 * This function is a wrapper for the mysqli_ping function, which checks whether the
 * connection to the server is working. If it has gone down, and the global option
 * mysqli.reconnect is enabled, it will attempt to reconnect. This is useful to ensure
 * that a connection is still alive and if not, to re-establish it before proceeding
 * with further operations. It returns TRUE if the connection is alive or if it was
 * successfully re-established, and FALSE if the connection is not established and
 * cannot be re-established.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_ping($connection)
{
    return mysqli_ping($connection);
}

/**
 * Returns the thread ID for the current connection.
 *
 * This function is a wrapper for the mysqli_thread_id function. It retrieves the thread ID used by
 * the current connection to the MySQL server. This ID can be used as an argument to the KILL
 * statement to terminate a connection. It is useful for debugging and managing MySQL connections
 * and can be used to uniquely identify the connection within the server's process.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return int The thread ID for the current connection.
 */
function wpsqli_thread_id($connection)
{
    return mysqli_thread_id($connection);
}

/**
 * Returns whether the client library is thread-safe.
 *
 * This function is a wrapper for the mysqli_thread_safe function. It indicates whether the
 * mysqli client library that PHP is using is thread-safe. This is important information when
 * running PHP in a multi-threaded environment such as with the worker MPM in Apache or when
 * using multi-threading extensions in PHP.
 *
 * @return bool Returns TRUE if the client library is thread-safe, FALSE otherwise.
 */
function wpsqli_thread_safe()
{
    return mysqli_thread_safe();
}

/**
 * Gets the current system status of the MySQL server.
 *
 * This function is a wrapper for the mysqli_stat function. It returns a string containing
 * status information about the MySQL server to which it's connected. The information includes
 * uptime, threads, queries, open tables, and flush tables, among other status indicators.
 * This can be useful for monitoring the health and performance of the MySQL server, as well
 * as for debugging purposes.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return string A string describing the server status or FALSE on failure.
 */
function wpsqli_stat($connection)
{
    return mysqli_stat($connection);
}

/**
 * Sets extra connect options and affect behavior for a connection.
 *
 * This function is a wrapper for the mysqli_options function. It is used to set extra options
 * for a connection resource before establishing a connection using mysqli_real_connect(). These
 * options can be used to control various aspects of the connection's behavior. The function should
 * be called after mysqli_init() and before mysqli_real_connect(). It returns TRUE on success or
 * FALSE on failure.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param int $option The specific option that is to be set.
 * @param mixed $value The value for the specified option.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_options($connection, $option, $value)
{
    return mysqli_options($connection, $option, $value);
}

/**
 * Returns the error code from the last connection attempt.
 *
 * This function is a wrapper for the mysqli_connect_errno function. It returns the error code from
 * the last call to mysqli_connect() or mysqli_real_connect(). It is useful for error handling after
 * attempting to establish a connection to a MySQL server, allowing the script to respond appropriately
 * to specific error conditions. The function does not take any parameters and returns an integer error
 * code. If no error occurred during the last connection attempt, it will return zero.
 *
 * @return int The error code from the last connection attempt.
 */
function wpsqli_connect_errno()
{
    return mysqli_connect_errno();
}

/**
 * Returns a string description of the last connect error.
 *
 * This function is a wrapper for the mysqli_connect_error function. It provides a textual description
 * of the error from the last connection attempt made by mysqli_connect() or mysqli_real_connect().
 * Unlike mysqli_connect_errno(), which returns an error code, mysqli_connect_error() returns a string
 * describing the error. This is useful for error handling, providing more detailed context about
 * connection problems.
 *
 * @return string|null A string that describes the error from the last connection attempt, or NULL
 *                     if no error occurred.
 */
function wpsqli_connect_error()
{
    return mysqli_connect_error();
}

/**
* Transaction Handling
*/

/**
 * Turns on or off auto-commit mode on queries for the database connection.
 *
 * This function is a wrapper for the mysqli_autocommit function. When turned on, each query
 * that you execute will automatically commit to the database. When turned off, you will need to
 * manually commit transactions using mysqli_commit() or rollback using mysqli_rollback(). This
 * function is particularly useful for transactions that require multiple steps and you don't want
 * to commit until all steps are successful.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param bool $mode Whether to turn on auto-commit mode or not. Pass TRUE to turn on auto-commit
 *                   mode and FALSE to turn it off.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_autocommit($connection, $mode)
{
    return mysqli_autocommit($connection, $mode);
}

/**
 * Starts a new transaction.
 *
 * This function is a wrapper for the mysqli_begin_transaction function. It starts a new transaction
 * with the provided connection and with the specified flags. Transactions allow multiple changes to
 * be made to the database atomically - they will all be applied, or none will be, which can be controlled
 * by committing or rolling back the transaction. This function can also set a name for the transaction,
 * which can be used for savepoints.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param int $flags Optional flags for defining transaction characteristics. This should be a bitmask
 *                   of any of the MYSQLI_TRANS_START_* constants.
 * @param string|null $name Optional name for the transaction, used for savepoint names.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_begin_transaction($connection, $flags = 0, $name = null)
{
    return mysqli_begin_transaction($connection, $flags, $name);
}

/**
 * Commits the current transaction.
 *
 * This function is a wrapper for the mysqli_commit function. It is used to commit the current transaction
 * for the database connection. Committing a transaction means that all the operations performed since the
 * start of the transaction are permanently saved to the database. This function can also take optional flags
 * and a name, the latter being used if the commit should be associated with a named savepoint.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param int $flags Optional flags for the commit operation. It should be a bitmask of the MYSQLI_TRANS_COR_* constants.
 * @param string|null $name Optional name for the savepoint that should be committed.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_commit($connection, $flags = 0, $name = null)
{
    return mysqli_commit($connection, $flags, $name);
}

/**
 * Rolls back the current transaction for the database connection.
 *
 * This function is a wrapper for the mysqli_rollback function. It rolls back the current transaction,
 * undoing all changes made to the database in the current transaction. This is an essential feature
 * for maintaining data integrity, especially in situations where a series of database operations need
 * to be treated as an atomic unit. The function can also accept optional flags and a name, which can be
 * used to rollback to a named savepoint within the transaction rather than rolling back the entire transaction.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param int $flags Optional flags that define how the rollback operation should be handled. It should be
 *                   a bitmask of the MYSQLI_TRANS_COR_* constants.
 * @param string|null $name Optional name of the savepoint to which the rollback operation should be directed.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_rollback($connection, $flags = 0, $name = null)
{
    return mysqli_rollback($connection, $flags, $name);
}

/**
* Database Operations
*/

/**
 * Selects the default database for database queries.
 *
 * This function is a wrapper for the mysqli_select_db function, which is used to change the default
 * database for the connection. This is useful when performing multiple operations across different
 * databases without having to establish a new connection for each one. If the function succeeds,
 * it will return TRUE, indicating the database was successfully selected, or FALSE if it fails.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param string $database The name of the database to select.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_select_db($connection, $database)
{
    return mysqli_select_db($connection, $database);
}

/**
 * Performs a query against the database.
 *
 * This function is a wrapper for the mysqli_query function. The mysqli_query function performs
 * a query against the database and returns a result set for successful SELECT queries, or TRUE
 * for other successful DML queries such as INSERT, UPDATE, DELETE, etc. It can also be used
 * to execute multiple queries if the database server supports it. The function can return FALSE
 * on failure. The optional third parameter defines the result mode - whether to use a resultset
 * buffering (MYSQLI_STORE_RESULT) or not (MYSQLI_USE_RESULT).
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param string $query The SQL query to be executed.
 * @param int $result_mode The optional mode for storing result set.
 * @return mixed Returns a mysqli_result object for successful SELECT queries, TRUE for other
 *               successful queries, or FALSE on failure.
 */
function wpsqli_query($connection, $query, $result_mode = MYSQLI_STORE_RESULT)
{
    return mysqli_query($connection, $query, $result_mode);
}

/**
 * Executes one or multiple queries which are concatenated by a semicolon.
 *
 * This function is a wrapper for the mysqli_multi_query function. It allows execution of
 * multiple SQL statements sent to the MySQL server in a single call. This can be useful to
 * perform a batch of SQL operations such as an atomic transaction that should either complete
 * entirely or not at all. After calling this function, the results of the queries can be
 * processed using mysqli_store_result() and mysqli_next_result(). It is important to ensure
 * that any user input included in the queries is properly sanitized to avoid SQL injection.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param string $query The queries to execute, concatenated by semicolons.
 * @return bool Returns TRUE on success or FALSE on the first error that occurred.
 *              If the first query succeeds, the function will return TRUE even if
 *              a subsequent query fails.
 */
function wpsqli_multi_query($connection, $query)
{
    return mysqli_multi_query($connection, $query);
}

/**
 * Prepares an SQL statement for execution.
 *
 * This function is a wrapper for the mysqli_prepare function. It prepares the SQL statement
 * and returns a statement object used for further operations on the statement. The statement
 * preparation is used to efficiently execute repeated queries with high efficiency and to avoid
 * SQL injection vulnerabilities by separating the query structure from its data. It is especially
 * useful when the same statement is executed multiple times with different parameters.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param string $query The SQL query to prepare.
 * @return mysqli_stmt|false Returns a statement object on success or FALSE on failure.
 */
function wpsqli_prepare($connection, $query)
{
    return mysqli_prepare($connection, $query);
}

/**
 * Executes a prepared Query.
 *
 * This function is a wrapper for the mysqli_stmt_execute function. It is used to execute a statement
 * that was previously prepared using the mysqli_prepare function. The execution will take place with
 * the current bound parameters in the statement object. This is commonly used in database operations
 * to execute the same statement repeatedly with high efficiency and to mitigate the risk of SQL injection
 * by separating SQL logic from the data being input.
 *
 * @param mysqli_stmt $stmt The mysqli_stmt statement object.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_stmt_execute($stmt)
{
    return mysqli_stmt_execute($stmt);
}

/**
 * Binds variables to a prepared statement as parameters.
 *
 * This function is a wrapper for the mysqli_stmt_bind_param function. It binds variables to the
 * placeholders of a prepared statement, which is represented by the `$stmt` parameter. The `$types`
 * parameter is a string that contains one character for each variable in `$vars`, indicating the type
 * of the variable. The supported types are 'i' for integer, 'd' for double, 's' for string, and 'b' for
 * blob. By using this function, the values of the variables are bound to the statement as it is executed,
 * which can be used to safely execute the statement with user-supplied input.
 *
 * @param mysqli_stmt $stmt The prepared statement to which the variables are bound.
 * @param string $types A string that contains a type specification char for each variable in `$vars`.
 * @param mixed ...$vars The variables to bind to the prepared statement.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_stmt_bind_param($stmt, $types, ...$vars)
{
    return mysqli_stmt_bind_param($stmt, $types, ...$vars);
}

/**
 * Binds variables to a prepared statement for result storage.
 *
 * This function is a wrapper for the mysqli_stmt_bind_result function. It binds variables to the
 * prepared statement `$stmt` to store the result of the statement once it is executed. The bound
 * variables are passed by reference and will be set to the values of the corresponding columns in
 * the result set. This function is typically used in conjunction with mysqli_stmt_fetch(), which
 * will populate the variables with data from the next row in the result set each time it is called.
 *
 * @param mysqli_stmt $stmt The statement object that executed a query with a result set.
 * @param mixed &...$vars The variables to which the result set columns will be bound.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_stmt_bind_result($stmt, &...$vars)
{
    return mysqli_stmt_bind_result($stmt, ...$vars);
}

/**
 * Fetches results from a prepared statement into the bound variables.
 *
 * This function is a wrapper for the mysqli_stmt_fetch function. It is used to fetch the data
 * from the executed prepared statement into the variables that were bound using mysqli_stmt_bind_result().
 * The function will return TRUE for every row fetched successfully. When there are no more rows to fetch,
 * it will return NULL, and if there is an error it will return FALSE.
 *
 * @param mysqli_stmt $stmt The prepared statement object from which results are to be fetched.
 * @return bool|null Returns TRUE on success, NULL if there are no more rows to fetch, or FALSE on error.
 */
function wpsqli_stmt_fetch($stmt)
{
    return mysqli_stmt_fetch($stmt);
}

/**
 * Closes a prepared statement.
 *
 * This function is a wrapper for the mysqli_stmt_close function. It deallocates the statement
 * and cleans up the memory associated with the statement object. This is an important step in
 * resource management, as it frees up server resources and allows other statements to be executed.
 * It should always be called after all the results have been fetched and the statement is no longer needed.
 *
 * @param mysqli_stmt $stmt The prepared statement object to be closed.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_stmt_close($stmt)
{
    return mysqli_stmt_close($stmt);
}

/**
 * Returns a string description for the last statement error.
 *
 * This function is a wrapper for the mysqli_stmt_error function. It returns a string describing
 * the error for the most recent statement operation that generated an error. This is useful for
 * debugging and error handling in applications that use prepared statements to interact with the
 * MySQL database. It allows developers to output or log a descriptive error message when a MySQL
 * operation on a prepared statement fails.
 *
 * @param mysqli_stmt $stmt The mysqli_stmt statement object.
 * @return string A string that describes the error. An empty string if no error occurred.
 */
function wpsqli_stmt_error($stmt)
{
    return mysqli_stmt_error($stmt);
}

/**
 * Returns the error code for the most recent statement call.
 *
 * This function is a wrapper for the mysqli_stmt_errno function. It returns the error code from
 * the last operation performed on the specified statement. This is useful for error handling,
 * particularly in database operations where you need to react differently based on the specific
 * error that occurred. It can be used in conjunction with mysqli_stmt_error() to retrieve both
 * the error code and the error message for more detailed debugging and logging.
 *
 * @param mysqli_stmt $stmt The mysqli_stmt statement object.
 * @return int An error code value for the last error that occurred, or zero if no error occurred.
 */
function wpsqli_stmt_errno($stmt)
{
    return mysqli_stmt_errno($stmt);
}

/**
* Result Handling
*/

/**
 * Fetches a result row as an associative, a numeric array, or both.
 *
 * This function is a wrapper for the mysqli_fetch_array function, which is used to fetch a single
 * row of data from the result set obtained from executing a SELECT query. The data can be fetched
 * as an associative array, a numeric array, or both, depending on the `mode` specified. By default,
 * it fetches as both associative and numeric (MYSQLI_BOTH). Using MYSQLI_ASSOC will fetch as an
 * associative array, and MYSQLI_NUM will fetch as a numeric array. It returns NULL when there are
 * no more rows to fetch.
 *
 * @param mysqli_result $result The result set from a query as returned by mysqli_query.
 * @param int $mode The type of array that should be produced from the current row data.
 * @return array|null Returns an array of strings that corresponds to the fetched row or NULL if
 *                    there are no more rows in result set.
 */
function wpsqli_fetch_array($result, $mode = MYSQLI_BOTH)
{
    return mysqli_fetch_array($result, $mode);
}

/**
 * Fetches a result row as an object.
 *
 * This function is a wrapper for the mysqli_fetch_object function. It retrieves the current row
 * of a result set as an object where the attributes correspond to the fetched row's column names.
 * This function can instantiate an object of a specified class, and pass parameters to its constructor,
 * allowing for custom objects based on the rows of the result set. If no class is specified, it defaults
 * to a stdClass object. If the class does not exist or the specified class's constructor requires more
 * arguments than are given, an exception is thrown.
 *
 * @param mysqli_result $result The result set returned by mysqli_query, mysqli_store_result
 *                              or mysqli_use_result.
 * @param string $class The name of the class to instantiate, set the properties of which
 *                      correspond to the fetched row's column names.
 * @param array $constructor_args An optional array of parameters to pass to the constructor
 *                                for the class name defined by the class parameter.
 * @return object|false An instance of the specified class with property names that correspond
 *                      to the column names returned in the result set, or FALSE on failure.
 */
function wpsqli_fetch_object($result, $class = "stdClass", $constructor_args = [])
{
    return mysqli_fetch_object($result, $class, $constructor_args);
}

/**
 * Fetches one row of data from the result set and returns it as an enumerated array.
 * Each call to this function will retrieve the next row in the result set, so it's typically
 * used in a loop to process multiple rows.
 *
 * This function is particularly useful when you need to retrieve a row as a simple array
 * where each column is accessed by an integer index starting at 0. It does not include
 * column names as keys, which can be marginally faster and less memory intensive than
 * associative arrays if the column names are not required.
 *
 * @param mysqli_result $result The result set returned by a query against the database.
 *
 * @return array|null Returns an enumerated array of strings representing the fetched row,
 * or NULL if there are no more rows in the result set.
 */
function wpsqli_fetch_row(mysqli_result $result): ?array
{
    return mysqli_fetch_row($result);
}

/**
 * Adjusts the result pointer to an arbitrary row in the result set represented by the
 * $result object. This function can be used in conjunction with mysqli_fetch_row(),
 * mysqli_fetch_assoc(), mysqli_fetch_array(), or mysqli_fetch_object() to navigate between
 * rows in result sets, especially when using buffered result sets.
 *
 * This is an important function for situations where you need to access a specific row
 * directly without iterating over all preceding rows, which can be useful for pagination
 * or when looking up specific rows by row number.
 *
 * @param mysqli_result $result The result set returned by a query against the database.
 * @param int $row_number The desired row number to seek to. Row numbers are zero-indexed.
 *
 * @return bool Returns TRUE on success or FALSE on failure. If the row number is out of range,
 * it returns FALSE.
 */
function wpsqli_data_seek(mysqli_result $result, int $row_number): bool
{
    return mysqli_data_seek($result, $row_number);
}

/**
 * Returns the next field in the result set.
 *
 * This function is a wrapper for the mysqli_fetch_field function, which retrieves information about
 * the next field in the result set represented by the `$result` parameter. It can be used in a loop
 * to obtain information about each field in the result set, such as name, table, max length, flags,
 * and type. This is useful for dynamically generating table structures or processing query results
 * when the structure of the result set is not known in advance or changes.
 *
 * @param mysqli_result $result The result set returned by mysqli_query, mysqli_store_result
 *                              or mysqli_use_result.
 * @return object An object which contains field definition information or FALSE if no field information
 *                is available.
 */
function wpsqli_fetch_field($result)
{
    return mysqli_fetch_field($result);
}

/**
 * Gets the number of fields in a result set.
 *
 * This function is a wrapper for the mysqli_num_fields function. It returns the number
 * of fields (columns) in a result set. This is particularly useful when you need to
 * dynamically process a query result without knowing the schema of the returned data,
 * as it allows the script to iterate over all fields in each row of the result set.
 *
 * @param mysqli_result $result The result set returned by mysqli_query, mysqli_store_result
 *                              or mysqli_use_result.
 * @return int The number of fields in the specified result set.
 */
function wpsqli_num_fields($result)
{
    return mysqli_num_fields($result);
}

/**
 * Returns the number of columns for the most recent query on the connection.
 *
 * This function is a wrapper for the mysqli_field_count function. It retrieves the number of
 * columns obtained from the most recent query executed on the given database connection. This
 * can be particularly useful when you need to know how many columns will be returned by a
 * SELECT statement before fetching data, which can help in dynamically processing result sets.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return int An integer representing the number of fields in the result set.
 */
function wpsqli_field_count($connection)
{
    return mysqli_field_count($connection);
}

/**
 * Transfers a result set from the last query.
 *
 * This function is a wrapper for the mysqli_store_result function. It is used to transfer the
 * result set from the last query executed on the given connection, which used the MYSQLI_STORE_RESULT
 * flag. This function must be called after executing a query that returns a result set (like SELECT).
 * It allows the complete result set to be transferred to the client and then utilized via the
 * mysqli_fetch_* functions. It's particularly useful when the result set is expected to be accessed
 * multiple times.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return mysqli_result|false A buffered result object or FALSE if an error occurred.
 */
function wpsqli_store_result($connection)
{
    return mysqli_store_result($connection);
}

/**
 * Initiates the retrieval of a result set from the last query executed using the MYSQLI_USE_RESULT mode.
 *
 * This function is a wrapper for the mysqli_use_result function. It is used to initiate the retrieval
 * of a result set from the last query executed on the given connection, without storing the entire result
 * set in the buffer. This is particularly useful for handling large result sets that could potentially
 * exceed the available PHP memory. The data is fetched row-by-row, reducing the immediate memory footprint.
 * However, it requires the connection to remain open, and no other operations can be performed on the
 * connection until the result set is fully processed.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return mysqli_result|false An unbuffered result object or FALSE if an error occurred.
 */
function wpsqli_use_result($connection)
{
    return mysqli_use_result($connection);
}

/**
 * Frees the memory associated with a result.
 *
 * This function is a wrapper for the mysqli_free_result function. It's used to free the memory
 * allocated for a result set obtained from a query. When the result data is not needed anymore,
 * it's a good practice to free the associated resources, especially when dealing with large
 * datasets that can consume significant amounts of memory. It is an important aspect of resource
 * management and helps to keep the application's memory footprint minimal.
 *
 * @param mysqli_result $result The result set returned by mysqli_query, mysqli_store_result
 *                              or mysqli_use_result.
 * @return void This function doesn't return any value.
 */
function wpsqli_free_result($result)
{
    return mysqli_free_result($result);
}

/**
 * Checks if there are any more result sets from a multi query.
 *
 * This function is a wrapper for the mysqli_more_results function. It is used after executing
 * a multi query with mysqli_multi_query() to check if there are more result sets available.
 * This is important when processing multiple SQL statements in one call, as it determines
 * whether the application should keep reading results before sending more statements to the server.
 * It returns TRUE if one or more result sets are available from the previous calls to
 * mysqli_multi_query(), otherwise FALSE.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return bool Returns TRUE if there are more result sets from previous multi queries and
 *              FALSE otherwise.
 */
function wpsqli_more_results($connection)
{
    return mysqli_more_results($connection);
}

/**
 * Moves the internal result pointer to the next result set returned from a multi query.
 *
 * This function is a wrapper for the mysqli_next_result function, which is used in a multi query
 * scenario. After executing mysqli_multi_query(), which can send multiple SQL statements to the
 * server at once, mysqli_next_result() checks for more result sets and prepares the next one for
 * reading. This is crucial for handling multiple operations executed with mysqli_multi_query() to
 * ensure that all result sets are processed sequentially. It returns TRUE if there is another result set,
 * FALSE if there are no more result sets, or FALSE with an error if there is a problem moving the result pointer.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return bool Returns TRUE on success or FALSE on failure (no more results or an error occurred).
 */
function wpsqli_next_result($connection)
{
    return mysqli_next_result($connection);
}

/**
* Utility Functions
*/

function wpsqli_is_resource($object)
{
    return $object !== false && $object !== null;
}

/**
 * Gets the number of affected rows in the previous MySQL operation.
 *
 * This function is a wrapper for the mysqli_affected_rows function, which is used to determine
 * the number of rows affected by the last INSERT, UPDATE, REPLACE or DELETE query executed on
 * the given connection. It is an important function for understanding the impact of such queries,
 * allowing the developer to verify that the expected number of rows were altered. It returns an
 * integer indicating the number of rows affected or -1 if the last query failed.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return int The number of affected rows in the previous operation, or -1 if the last operation failed.
 */
function wpsqli_affected_rows($connection)
{
    return mysqli_affected_rows($connection);
}

/**
 * Retrieves the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute.
 *
 * This function is a wrapper for the mysqli_insert_id function, which returns the auto generated id
 * used in the last query. It is typically used after an INSERT query into a table with an auto-increment
 * field. The id returned is the one that was automatically generated for the AUTO_INCREMENT column in
 * the affected table. If the last query wasn't an INSERT or UPDATE statement or didn't affect an
 * AUTO_INCREMENT column, or if the AUTO_INCREMENT value was set to a non-positive value manually,
 * this function will return zero.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return int|string The ID generated for an AUTO_INCREMENT column by the previous query on success, 0 if the previous
 *                    query does not generate an AUTO_INCREMENT value, or FALSE on failure.
 */
function wpsqli_insert_id($connection)
{
    return mysqli_insert_id($connection);
}


/**
 * Sets the default character set to be used when sending data from and to the database server.
 *
 * This function is a wrapper for the mysqli_set_charset function. The mysqli_set_charset function
 * is used to set the character set to be used when sending data from and to the database server.
 * This is particularly important to ensure that data is properly encoded and decoded when stored
 * and retrieved from the database, avoiding character encoding issues.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param string $charset The desired character set.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_set_charset($connection, $charset)
{
    return mysqli_set_charset($connection, $charset);
}

/**
 * Escapes special characters in a string for use in an SQL statement.
 *
 * This function serves as a wrapper for the mysqli_real_escape_string function, which is
 * utilized to escape potentially dangerous special characters within a string. This is a
 * critical security measure to prevent SQL injection vulnerabilities by ensuring that user
 * input can be safely used in an SQL query. The function takes a string to be escaped and
 * the mysqli connection resource, and returns the escaped string which is safe to be included
 * in SQL statements.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @param string $string The string to be escaped.
 * @return string Returns the escaped string.
 */
function wpsqli_real_escape_string($connection, $string)
{
    return mysqli_real_escape_string($connection, $string);
}

/**
 * Retrieves the last error description for the most recent MySQLi function call
 * that can succeed or fail.
 *
 * This function is a wrapper for the mysqli_error function, which returns a string
 * describing the error from the last MySQL operation associated with the provided
 * connection resource. It's an essential function for debugging and error handling
 * in MySQL-related operations. When a MySQLi function fails, wpsqli_error can be
 * used to fetch the corresponding error message to understand what went wrong.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return string Returns a string with the error message for the most recent function call
 *                if it has failed, or an empty string if no error has occurred.
 */
function wpsqli_error($connection)
{
    return mysqli_error($connection);
}

/**
 * Retrieves the error code for the most recent function call that failed.
 *
 * This function is a wrapper for the mysqli_errno function. It returns the error code from
 * the last error that occurred during a MySQL operation on the given connection. This code
 * can be used in conjunction with mysqli_error() to provide a detailed explanation of the
 * error, especially for logging or for generating user-friendly error messages.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return int Returns an error code value representing the error from the last MySQL operation
 *             on the given connection, or zero if no error occurred.
 */
function wpsqli_errno($connection)
{
    return mysqli_errno($connection);
}

/**
 * Enables or disables internal report functions.
 *
 * This function is a wrapper for the mysqli_report function, which is used to set the
 * reporting mode of mysqli errors. This is useful for defining whether errors should be
 * reported as exceptions, warnings, or silent (no report). It's important for configuring
 * the error reporting behavior of the mysqli extension to suit the needs of your application,
 * particularly in a development environment where more verbose error reporting is beneficial.
 *
 * @param int $flags A bit-mask constructed from the MYSQLI_REPORT_* constants.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_report($flags)
{
    return mysqli_report($flags);
}

/**
 * Retrieves information about the most recently executed query.
 *
 * This function is a wrapper for the mysqli_info function. It provides a string containing
 * information about the most recently executed query on the given connection resource. This
 * can include information such as the number of rows affected by an INSERT, UPDATE, REPLACE,
 * or DELETE query, as well as the number of rows matched and changed. It is valuable for
 * obtaining detailed insights into the execution of database operations.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return string|null A string representing information about the last query executed,
 *                     or NULL if no information is available.
 */
function wpsqli_info($connection)
{
    return mysqli_info($connection);
}

/**
 * Initializes a statement and returns an object for use with mysqli_stmt_prepare.
 *
 * This function is a wrapper for the mysqli_stmt_init function. It creates and returns a new statement
 * object associated with the specified database connection. This statement object can then be used
 * to prepare a SQL statement for execution. It's particularly useful when you need to execute a
 * prepared statement multiple times with different parameters, providing benefits such as improved
 * query performance and protection against SQL injection attacks.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return mysqli_stmt A new statement object or FALSE on failure.
 */
function wpsqli_stmt_init($connection)
{
    return mysqli_stmt_init($connection);
}

/**
 * Polls connections for results.
 *
 * This function is a wrapper for the mysqli_poll function. It can be used to poll multiple
 * connections to check if one or more of the connections have results available for client-side
 * processing. It is useful when you have multiple asynchronous queries running and need to handle
 * them as soon as their results become available. The function takes variable references for read,
 * error, and reject arrays, and modifies them to indicate which connections have results, which
 * have errors, and which were rejected respectively.
 *
 * @param array &$read Array of connections to check for outstanding results that can be read.
 * @param array &$error Array of connections on which an error occurred.
 * @param array &$reject Array of connections rejected because no asynchronous query
 *                       has been run on them.
 * @param int $sec Number of seconds to wait, must be non-negative.
 * @param int $usec Number of microseconds to wait, must be non-negative.
 * @return int|false Number of ready connections upon success, FALSE otherwise.
 */
function wpsqli_poll(&...$args)
{
    return mysqli_poll(...$args);
}

/**
 * Gets the result from asynchronous MySQL query.
 *
 * This function is a wrapper for the mysqli_reap_async_query function. It is used after initiating
 * a query with mysqli_query() on a connection with the MYSQLI_ASYNC flag set. It retrieves the result
 * from the query once it is complete, which can be used with mysqli_poll() to manage multiple
 * asynchronous queries. It returns a mysqli_result object for successful SELECT queries, or TRUE for
 * other DML queries (INSERT, UPDATE, DELETE, etc.) if the operation was successful, or FALSE on failure.
 *
 * @param mysqli $connection The mysqli connection resource.
 * @return mysqli_result|bool A mysqli_result object for successful SELECT queries, TRUE for other
 *                            successful DML queries, or FALSE on failure.
 */
function wpsqli_reap_async_query($connection)
{
    return mysqli_reap_async_query($connection);
}


================================================
FILE: pg4wp/driver_pgsql.php
================================================
<?php

include_once PG4WP_ROOT . '/driver_pgsql_rewrite.php';

/**
* This file implements the postgreSQL driver
* This file remaps all wpsqli_* calls to postgres equivalents
*/
if (!extension_loaded('pgsql')) {
    wp_die('Your PHP installation appears to be missing the PostgreSQL extension which is required by WordPress with PG4WP.');
}

// Initializing some variables
$GLOBALS['pg4wp_version'] = '7.0';
$GLOBALS['pg4wp_result'] = 0;
$GLOBALS['pg4wp_numrows_query'] = '';
$GLOBALS['pg4wp_ins_table'] = '';
$GLOBALS['pg4wp_ins_field'] = '';
$GLOBALS['pg4wp_ins_id'] = '';
$GLOBALS['pg4wp_last_insert'] = '';
$GLOBALS['pg4wp_connstr'] = '';
$GLOBALS['pg4wp_conn'] = false;

/**
* Connection Handling
*/


/**
 * No direct equivalent in PostgreSQL. Connections are established directly.
 * Returns a fake connection class which does nothing
 */
function wpsqli_init()
{
    return new class () {
        public $sslkey;
        public $sslcert;
        public $sslca;
        public $sslcapath;
        public $sslcipher;
    };
}

/**
 * Opens a connection to a PostgreSQL server in a real context.
 *
 * This function is a wrapper for the pg_connect function, which attempts to establish
 * a connection to a PostgreSQL server. The function takes in parameters for the host name, username,
 * password, database name, port number, socket, and flags, The flags parameter can be used to set different
 * connection options that can affect the behavior of the connection.
 *
 * @param $connection dummy parameter just for compatibility with mysqli
 * @param string|null $hostname The host name or an IP address.
 * @param string|null $username The PostgreSQL user name.
 * @param string|null $password The password associated with the username.
 * @param string|null $database The default database to be used when performing queries.
 * @param int|null $port The port number to attempt to connect to the PostgreSQL server.
 * @param string|null $socket The socket or named pipe that should be used.
 * @param int $flags Client connection flags.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_real_connect(&$connection, $hostname = null, $username = null, $password = null, $database = null, $port = null, $socket = null, $flags = 0)
{
    $GLOBALS['pg4wp_connstr'] = '';

    if (!empty($hostname)) {
        $GLOBALS['pg4wp_connstr'] .= ' host=' . $hostname;
    }

    if (!empty($port)) {
        $GLOBALS['pg4wp_connstr'] .= ' port=' . $port;
    }

    if (!empty($username)) {
        $GLOBALS['pg4wp_connstr'] .= ' user=' . $username;
    }

    if (!empty($password)) {
        $GLOBALS['pg4wp_connstr'] .= ' password=' . $password;
    }

    // SSL parameters
    if (!empty($connection->sslkey)) {
        $GLOBALS['pg4wp_connstr'] .= ' sslkey=' . $connection->sslkey;
    }

    if (!empty($connection->sslcert)) {
        $GLOBALS['pg4wp_connstr'] .= ' sslcert=' . $connection->sslcert;
    }

    if (!empty($connection->sslca)) {
        $GLOBALS['pg4wp_connstr'] .= ' sslrootcert=' . $connection->sslca;
    }

    if (!empty($connection->sslcapath)) {
        $GLOBALS['pg4wp_connstr'] .= ' sslcapath=' . $connection->sslcapath;
    }

    if (!empty($connection->sslcipher)) {
        $GLOBALS['pg4wp_connstr'] .= ' sslcipher=' . $connection->sslcipher;
    }

    // Must connect to a specific database unlike MySQL
    $dbname = defined('DB_NAME') && DB_NAME ? DB_NAME : $database;
    $pg_connstr = $GLOBALS['pg4wp_connstr'] . ' dbname=' . $dbname;
    $GLOBALS['pg4wp_conn'] = $connection = pg_connect($pg_connstr);

    return $connection;
}

/**
* Database Operations
*/

/**
 * Selects the default database for database queries.
 *
 * This function is a wrapper for the pg_select_db function, which is used to change the default
 * database for the connection. This is useful when performing multiple operations across different
 * databases without having to establish a new connection for each one. If the function succeeds,
 * it will return TRUE, indicating the database was successfully selected, or FALSE if it fails.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param string $database The name of the database to select.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_select_db(&$connection, $database)
{
    $pg_connstr = $GLOBALS['pg4wp_connstr'] . ' dbname=' . $database;
    $GLOBALS['pg4wp_conn'] = $connection = pg_connect($pg_connstr);

    // Return FALSE if connection failed
    if(!$connection) {
        return $connection;
    }

    // Get and store PostgreSQL server version
    $ver = pg_version($connection);
    if(isset($ver['server'])) {
        $GLOBALS['pg4wp_version'] = $ver['server'];
    }

    // Clear the connection string unless this is a test connection
    if(!defined('WP_INSTALLING') || !WP_INSTALLING) {
        $GLOBALS['pg4wp_connstr'] = '';
    }

    // Execute any pre-defined SQL commands
    if(!empty($GLOBALS['pg4wp_pre_sql'])) {
        foreach($GLOBALS['pg4wp_pre_sql'] as $sql2run) {
            wpsqli_query($sql2run);
        }
    }

    return $connection;
}

/**
 * Closes a previously opened database connection.
 *
 * This function is a wrapper for the pg_close function.
 * // mysqli_close => pg_close (resource $connection): bool
 * It's important to close connections when they are no longer needed to free up resources on both the web
 * server and the PostgreSQL server. The function returns TRUE on success or FALSE on failure.
 *
 * @param PgSql\Connection $connection The pg connection resource to be closed.
 * @return bool Returns TRUE on successful closure, FALSE on failure.
 */
function wpsqli_close(&$connection)
{
    // Closing a connection in PostgreSQL is straightforward.
    return pg_close($connection);
}

/**
 * Used to establish secure connections using SSL.
 *
 * This function sets up variables on the fake pg connection class which are used when
 * connecting to the postgres database with pg_connect
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param string $key The path to the key file.
 * @param string $cert The path to the certificate file.
 * @param string $ca The path to the certificate authority file.
 * @param string $capath The pathname to a directory that contains trusted SSL CA certificates
 *                       in PEM format.
 * @param string $cipher A list of allowable ciphers to use for SSL encryption.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_ssl_set(&$connection, $key, $cert, $ca, $capath, $cipher)
{
    $connection->sslkey = $key;
    $connection->sslcert = $cert;
    $connection->sslca = $ca;
    $connection->sslcapath = $capath;
    $connection->sslcipher = $cipher;
    return $connection;
}

/**
 * Returns the PostgreSQL client library version as a string.
 *
 * This function is used to retrieve the version of the client library that is used to compile the pg extension. The function
 * does not require any parameters and can be called statically. It is helpful for debugging
 * and ensuring that the PHP environment is using the correct version of the PostgreSQL client library,
 * which can be important for compatibility and functionality reasons.
 *
 * @return string The PostgreSQL client library version.
 */
function wpsqli_get_client_info()
{
    // mysqli_get_client_info => No direct equivalent.
    // Information can be derived from phpinfo() or phpversion().
    return '8.0.35'; // Just want to fool wordpress ...
}

/**
 * Retrieves the version of the PostgreSQL server.
 *
 * This function returns a string representing the version of the PostgreSQL server pointed to by the connection resource. This
 * information can be used for a variety of purposes, such as conditional behavior for different
 * PostgreSQL versions or simply for logging and monitoring. Understanding the server version is
 * essential for ensuring compatibility with specific PostgreSQL features and syntax.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return string The version of the PostgreSQL server.
 */
function wpsqli_get_server_info(&$connection)
{
    // mysqli_get_server_info => pg_version (resource $connection): array
    // This function retrieves an array that includes server version.
    // pg_version($connection);
    return '8.0.35'; // Just want to fool wordpress ...
}

/**
 * Returns a string representing the type of connection used.
 *
 * This function is a wrapper for the pg_get_host_info function. It retrieves information about
 * the type of connection that was established to the PostgreSQL server and the host server information.
 * This includes the host name and the connection type, such as TCP/IP or a UNIX socket. It's useful
 * for debugging and for understanding how PHP is communicating with the PostgreSQL server.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return string A string describing the connection type and server host information.
 */
function wpsqli_host_info(&$connection)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_get_host_info => No direct equivalent. Host information is part of the connection string in PostgreSQL.
}

/**
 * Pings a server connection, or tries to reconnect if the connection has gone down.
 *
 * This function is a wrapper for the pg_ping function, which checks whether the
 * connection to the server is working. If it has gone down, and the global option
 * pg.reconnect is enabled, it will attempt to reconnect. This is useful to ensure
 * that a connection is still alive and if not, to re-establish it before proceeding
 * with further operations. It returns TRUE if the connection is alive or if it was
 * successfully re-established, and FALSE if the connection is not established and
 * cannot be re-established.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_ping(&$connection)
{
    return pg_ping($connection);
}

/**
 * Returns the thread ID for the current connection.
 *
 * This function is a wrapper for the pg_thread_id function. It retrieves the thread ID used by
 * the current connection to the PostgreSQL server. This ID can be used as an argument to the KILL
 * statement to terminate a connection. It is useful for debugging and managing PostgreSQL connections
 * and can be used to uniquely identify the connection within the server's process.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return int The thread ID for the current connection.
 */
function wpsqli_thread_id(&$connection)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_thread_id => No direct equivalent. PostgreSQL does not provide thread ID in the same manner as MySQL.
}

/**
 * Returns whether the client library is thread-safe.
 *
 * This function is a wrapper for the pg_thread_safe function. It indicates whether the
 * pg client library that PHP is using is thread-safe. This is important information when
 * running PHP in a multi-threaded environment such as with the worker MPM in Apache or when
 * using multi-threading extensions in PHP.
 *
 * @return bool Returns TRUE if the client library is thread-safe, FALSE otherwise.
 */
function wpsqli_thread_safe()
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_thread_safe => No direct equivalent. PostgreSQL's thread safety is dependent on PHP's thread safety.
}

/**
 * Gets the current system status of the PostgreSQL server.
 *
 * This function is a wrapper for the pg_stat function. It returns a string containing
 * status information about the PostgreSQL server to which it's connected. The information includes
 * uptime, threads, queries, open tables, and flush tables, among other status indicators.
 * This can be useful for monitoring the health and performance of the PostgreSQL server, as well
 * as for debugging purposes.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return string A string describing the server status or FALSE on failure.
 */
function wpsqli_stat(&$connection)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_stat => No direct equivalent
}

/**
 * Sets extra connect options and affect behavior for a connection.
 *
 * This function is a wrapper for the pg_options function. It is used to set extra options
 * for a connection resource before establishing a connection using pg_real_connect(). These
 * options can be used to control various aspects of the connection's behavior. The function should
 * be called after pg_init() and before pg_real_connect(). It returns TRUE on success or
 * FALSE on failure.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param int $option The specific option that is to be set.
 * @param mixed $value The value for the specified option.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_options(&$connection, $option, $value)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_options => No direct equivalent. Options are set in the connection string or via set_config in PostgreSQL.
}

/**
 * Returns the error code from the last connection attempt.
 *
 * This function is a wrapper for the pg_connect_errno function. It returns the error code from
 * the last call to pg_connect() or pg_real_connect(). It is useful for error handling after
 * attempting to establish a connection to a PostgreSQL server, allowing the script to respond appropriately
 * to specific error conditions. The function does not take any parameters and returns an integer error
 * code. If no error occurred during the last connection attempt, it will return zero.
 *
 * @return int The error code from the last connection attempt.
 */
function wpsqli_connect_errno()
{
    throw new \Exception("PG4WP: Not Yet Implemented");
}

/**
 * Returns a string description of the last connect error.
 *
 * This function is a wrapper for the pg_connect_error function. It provides a textual description
 * of the error from the last connection attempt made by pg_connect() or pg_real_connect().
 * Unlike pg_connect_errno(), which returns an error code, pg_connect_error() returns a string
 * describing the error. This is useful for error handling, providing more detailed context about
 * connection problems.
 *
 * @return string|null A string that describes the error from the last connection attempt, or NULL
 *                     if no error occurred.
 */
function wpsqli_connect_error()
{
    if($GLOBALS['pg4wp_conn']) {
        return pg_last_error($GLOBALS['pg4wp_conn']);
    }

    return '';
}

/**
* Transaction Handling
*/

/**
 * Turns on or off auto-commit mode on queries for the database connection.
 *
 * This function is a wrapper for the pg_autocommit function. When turned on, each query
 * that you execute will automatically commit to the database. When turned off, you will need to
 * manually commit transactions using pg_commit() or rollback using pg_rollback(). This
 * function is particularly useful for transactions that require multiple steps and you don't want
 * to commit until all steps are successful.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param bool $mode Whether to turn on auto-commit mode or not. Pass TRUE to turn on auto-commit
 *                   mode and FALSE to turn it off.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_autocommit(&$connection, $mode)
{
    // mysqli_autocommit => pg_autocommit (resource $connection, bool $mode): bool
    // PostgreSQL autocommit behavior is typically managed at the transaction level.
    pg_query($connection, "SET AUTOCOMMIT TO ON");
}

/**
 * Starts a new transaction.
 *
 * This function is a wrapper for the pg_begin_transaction function. It starts a new transaction
 * with the provided connection and with the specified flags. Transactions allow multiple changes to
 * be made to the database atomically - they will all be applied, or none will be, which can be controlled
 * by committing or rolling back the transaction. This function can also set a name for the transaction,
 * which can be used for savepoints.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param int $flags Optional flags for defining transaction characteristics. This should be a bitmask
 *                   of any of the pg_TRANS_START_* constants.
 * @param string|null $name Optional name for the transaction, used for savepoint names.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_begin_transaction(&$connection, $flags = 0, $name = null)
{
    // mysqli_begin_transaction => pg_query (resource $connection, string $query): resource
    // PostgreSQL uses standard BEGIN or START TRANSACTION queries.
    pg_query($connection, "BEGIN");
}

/**
 * Commits the current transaction.
 *
 * This function is a wrapper for the pg_commit function. It is used to commit the current transaction
 * for the database connection. Committing a transaction means that all the operations performed since the
 * start of the transaction are permanently saved to the database. This function can also take optional flags
 * and a name, the latter being used if the commit should be associated with a named savepoint.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param int $flags Optional flags for the commit operation. It should be a bitmask of the pg_TRANS_COR_* constants.
 * @param string|null $name Optional name for the savepoint that should be committed.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_commit(&$connection, $flags = 0, $name = null)
{
    // mysqli_commit => pg_query (resource $connection, string $query): resource
    // Commits are standard SQL in PostgreSQL.
    pg_query($connection, "COMMIT");
}

/**
 * Rolls back the current transaction for the database connection.
 *
 * This function is a wrapper for the pg_rollback function. It rolls back the current transaction,
 * undoing all changes made to the database in the current transaction. This is an essential feature
 * for maintaining data integrity, especially in situations where a series of database operations need
 * to be treated as an atomic unit. The function can also accept optional flags and a name, which can be
 * used to rollback to a named savepoint within the transaction rather than rolling back the entire transaction.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param int $flags Optional flags that define how the rollback operation should be handled. It should be
 *                   a bitmask of the pg_TRANS_COR_* constants.
 * @param string|null $name Optional name of the savepoint to which the rollback operation should be directed.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_rollback(&$connection, $flags = 0, $name = null)
{
    // mysqli_rollback => pg_query (resource $connection, string $query): resource
    // Rollbacks are standard SQL in PostgreSQL.
    pg_query($connection, "ROLLBACK");
}

function get_primary_key_for_table(&$connection, $table)
{
    $query = <<<SQL
    SELECT a.attname, i.indisprimary 
        FROM   pg_index i 
        JOIN   pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
        WHERE  i.indrelid = '$table'::regclass
    SQL;

    $result = pg_query($connection, $query);
    if (!$result) {
        return null;
    }

    $firstRow = null;
    while ($row = pg_fetch_row($result)) {
        if ($firstRow === null) {
            $firstRow = $row; // Save the first row in case no match is found
        }
        
        if ($row[1] == true) {
            return $row[0]; // Return the first row where $row[1] == true
        }
    }

    // If no row where $row[1] == true was found, return the first row encountered
    return $firstRow ? $firstRow[0] : null;
}

/**
 * Performs a query against the database.
 *
 * This function is a wrapper for the pg_query function. The pg_query function performs
 * a query against the database and returns a result set for successful SELECT queries, or TRUE
 * for other successful DML queries such as INSERT, UPDATE, DELETE, etc.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param string $query The SQL query to be executed.
 * @param int $result_mode The optional mode for storing result set.
 * @return mixed Returns a pg_result object for successful SELECT queries, TRUE for other
 *               successful queries, or FALSE on failure.
 */
function wpsqli_query(&$connection, $query, $result_mode = 0)
{
    // Check if a connection to Postgres database is established
    if (!$connection) {
        // Store SQL query for later execution when connection is available
        $GLOBALS['pg4wp_pre_sql'][] = $sql;
        return true;
    }

    // Store the initial SQL query
    $initial = $query;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($query);

    // Execute the SQL query and store the result
    if (PG4WP_DEBUG) {
        $result = pg_query($connection, $sql);
    } else {
        $result = @pg_query($connection, $sql);
    }

    // Handle errors and logging
    if ((PG4WP_DEBUG || PG4WP_LOG_ERRORS) && $result === false && $err = pg_last_error($connection)) {
        $ignore = false;
        // Ignore errors if WordPress is in the installation process
        if (defined('WP_INSTALLING') && WP_INSTALLING) {
            global $table_prefix;
            $ignore = strpos($err, 'relation "' . $table_prefix);
        }
        if (!$ignore) {
            error_log('[' . microtime(true) . "] Error running :\n$initial\n---- converted to ----\n$sql\n----> $err\n---------------------\n", 3, PG4WP_LOG . 'pg4wp_errors.log');
        }
    }

    $GLOBALS['pg4wp_conn'] = $connection;
    $GLOBALS['pg4wp_result'] = $result;

    if (false !== strpos($sql, "INSERT INTO")) {
        $matches = array();
        preg_match("/^INSERT INTO\s+`?([a-z0-9_]+)`?/i", $query, $matches);
        $tableName = $matches[1];

        if (false !== strpos($sql, "RETURNING")) {
            $primaryKey = get_primary_key_for_table($connection, $tableName);
            $row = pg_fetch_assoc($result);

            $GLOBALS['pg4wp_ins_id'] = $row[$primaryKey];
        }
    }

    return $result;
}

/**
 * Executes one or multiple queries which are concatenated by a semicolon.
 *
 * This function is a wrapper for the pg_multi_query function. It allows execution of
 * multiple SQL statements sent to the PostgreSQL server in a single call. This can be useful to
 * perform a batch of SQL operations such as an atomic transaction that should either complete
 * entirely or not at all. After calling this function, the results of the queries can be
 * processed using pg_store_result() and pg_next_result(). It is important to ensure
 * that any user input included in the queries is properly sanitized to avoid SQL injection.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param string $query The queries to execute, concatenated by semicolons.
 * @return bool Returns TRUE on success or FALSE on the first error that occurred.
 *              If the first query succeeds, the function will return TRUE even if
 *              a subsequent query fails.
 */
function wpsqli_multi_query(&$connection, $query)
{
    // Store the initial SQL query
    $initial = $query;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($query);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_multi_query => No direct equivalent. Multiple queries must be executed separately in PostgreSQL.
}

/**
 * Prepares an SQL statement for execution.
 *
 * This function is a wrapper for the pg_prepare function. It prepares the SQL statement
 * and returns a statement object used for further operations on the statement. The statement
 * preparation is used to efficiently execute repeated queries with high efficiency and to avoid
 * SQL injection vulnerabilities by separating the query structure from its data. It is especially
 * useful when the same statement is executed multiple times with different parameters.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param string $query The SQL query to prepare.
 * @return class|false Returns a statement object on success or FALSE on failure.
 */
function wpsqli_prepare(&$connection, $query)
{
    // Store the initial SQL query
    $initial = $query;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($query);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_prepare => pg_prepare (resource $connection, string $stmtname, string $query): resource
    // pg_prepare($connection, "my_query", "SELECT * FROM my_table WHERE id = $1");
}

/**
 * Executes a prepared Query.
 *
 * This function is a wrapper for the pg_stmt_execute function. It is used to execute a statement
 * that was previously prepared using the pg_prepare function. The execution will take place with
 * the current bound parameters in the statement object. This is commonly used in database operations
 * to execute the same statement repeatedly with high efficiency and to mitigate the risk of SQL injection
 * by separating SQL logic from the data being input.
 *
 * @param pg_stmt $stmt The pg_stmt statement object.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_stmt_execute($stmt)
{
    // Store the initial SQL query
    $initial = $stmt;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($stmt);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_stmt_execute => pg_execute (resource $connection, string $stmtname, array $params): resource
    // Executes a previously prepared statement.
    // pg_execute($connection, "my_query", array("my_id"));
}

/**
 * Binds variables to a prepared statement as parameters.
 *
 * This function is a wrapper for the pg_stmt_bind_param function. It binds variables to the
 * placeholders of a prepared statement, which is represented by the `$stmt` parameter. The `$types`
 * parameter is a string that contains one character for each variable in `$vars`, indicating the type
 * of the variable. The supported types are 'i' for integer, 'd' for double, 's' for string, and 'b' for
 * blob. By using this function, the values of the variables are bound to the statement as it is executed,
 * which can be used to safely execute the statement with user-supplied input.
 *
 * @param pg_stmt $stmt The prepared statement to which the variables are bound.
 * @param string $types A string that contains a type specification char for each variable in `$vars`.
 * @param mixed ...$vars The variables to bind to the prepared statement.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_stmt_bind_param($stmt, $types, ...$vars)
{
    // Store the initial SQL query
    $initial = $stmt;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($stmt);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // The remaining mysqli_stmt_* functions do not have direct equivalents in PostgreSQL. Prepared statements work differently.
    // PostgreSQL uses pg_prepare() and pg_execute() for prepared statements. Results are then fetched with pg_fetch_* functions.
}

/**
 * Binds variables to a prepared statement for result storage.
 *
 * This function is a wrapper for the pg_stmt_bind_result function. It binds variables to the
 * prepared statement `$stmt` to store the result of the statement once it is executed. The bound
 * variables are passed by reference and will be set to the values of the corresponding columns in
 * the result set. This function is typically used in conjunction with pg_stmt_fetch(), which
 * will populate the variables with data from the next row in the result set each time it is called.
 *
 * @param pg_stmt $stmt The statement object that executed a query with a result set.
 * @param mixed &...$vars The variables to which the result set columns will be bound.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_stmt_bind_result($stmt, &...$vars)
{
    // Store the initial SQL query
    $initial = $stmt;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($stmt);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // The remaining mysqli_stmt_* functions do not have direct equivalents in PostgreSQL. Prepared statements work differently.
    // PostgreSQL uses pg_prepare() and pg_execute() for prepared statements. Results are then fetched with pg_fetch_* functions.
}

/**
 * Fetches results from a prepared statement into the bound variables.
 *
 * This function is a wrapper for the pg_stmt_fetch function. It is used to fetch the data
 * from the executed prepared statement into the variables that were bound using pg_stmt_bind_result().
 * The function will return TRUE for every row fetched successfully. When there are no more rows to fetch,
 * it will return NULL, and if there is an error it will return FALSE.
 *
 * @param pg_stmt $stmt The prepared statement object from which results are to be fetched.
 * @return bool|null Returns TRUE on success, NULL if there are no more rows to fetch, or FALSE on error.
 */
function wpsqli_stmt_fetch($stmt)
{
    // Store the initial SQL query
    $initial = $query;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($query);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // The remaining mysqli_stmt_* functions do not have direct equivalents in PostgreSQL. Prepared statements work differently.
    // PostgreSQL uses pg_prepare() and pg_execute() for prepared statements. Results are then fetched with pg_fetch_* functions.
}

/**
 * Initializes a statement and returns an object for use with pg_stmt_prepare.
 *
 * This function is a wrapper for the pg_stmt_init function. It creates and returns a new statement
 * object associated with the specified database connection. This statement object can then be used
 * to prepare a SQL statement for execution. It's particularly useful when you need to execute a
 * prepared statement multiple times with different parameters, providing benefits such as improved
 * query performance and protection against SQL injection attacks.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return class A new statement object or FALSE on failure.
 */
function wpsqli_stmt_init(&$connection)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_stmt_init => No direct equivalent in PostgreSQL.
    // In PostgreSQL, prepared statements are created directly with pg_prepare, not initialized separately.
}


/**
 * Closes a prepared statement.
 *
 * This function is a wrapper for the pg_stmt_close function. It deallocates the statement
 * and cleans up the memory associated with the statement object. This is an important step in
 * resource management, as it frees up server resources and allows other statements to be executed.
 * It should always be called after all the results have been fetched and the statement is no longer needed.
 *
 * @param pg_stmt $stmt The prepared statement object to be closed.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_stmt_close($stmt)
{
    // Store the initial SQL query
    $initial = $stmt;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($stmt);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // The remaining mysqli_stmt_* functions do not have direct equivalents in PostgreSQL. Prepared statements work differently.
    // PostgreSQL uses pg_prepare() and pg_execute() for prepared statements. Results are then fetched with pg_fetch_* functions.
}

/**
 * Returns a string description for the last statement error.
 *
 * This function is a wrapper for the pg_stmt_error function. It returns a string describing
 * the error for the most recent statement operation that generated an error. This is useful for
 * debugging and error handling in applications that use prepared statements to interact with the
 * PostgreSQL database. It allows developers to output or log a descriptive error message when a PostgreSQL
 * operation on a prepared statement fails.
 *
 * @param pg_stmt $stmt The pg_stmt statement object.
 * @return string A string that describes the error. An empty string if no error occurred.
 */
function wpsqli_stmt_error($stmt)
{
    // Store the initial SQL query
    $initial = $stmt;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($stmt);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // The remaining mysqli_stmt_* functions do not have direct equivalents in PostgreSQL. Prepared statements work differently.
    // PostgreSQL uses pg_prepare() and pg_execute() for prepared statements. Results are then fetched with pg_fetch_* functions.
}

/**
 * Returns the error code for the most recent statement call.
 *
 * This function is a wrapper for the pg_stmt_errno function. It returns the error code from
 * the last operation performed on the specified statement. This is useful for error handling,
 * particularly in database operations where you need to react differently based on the specific
 * error that occurred. It can be used in conjunction with pg_stmt_error() to retrieve both
 * the error code and the error message for more detailed debugging and logging.
 *
 * @param pg_stmt $stmt The pg_stmt statement object.
 * @return int An error code value for the last error that occurred, or zero if no error occurred.
 */
function wpsqli_stmt_errno($stmt)
{
    // Store the initial SQL query
    $initial = $stmt;
    // Rewrite the SQL query for compatibility with Postgres
    $sql = pg4wp_rewrite($stmt);
    throw new \Exception("PG4WP: Not Yet Implemented");
    // The remaining mysqli_stmt_* functions do not have direct equivalents in PostgreSQL. Prepared statements work differently.
    // PostgreSQL uses pg_prepare() and pg_execute() for prepared statements. Results are then fetched with pg_fetch_* functions.
}

/**
* Result Handling
*/

/**
 * Fetches a result row as an associative, a numeric array, or both.
 *
 * This function is a wrapper for the pg_fetch_array function, which is used to fetch a single
 * row of data from the result set obtained from executing a SELECT query. The data can be fetched
 * as an associative array, a numeric array, or both, depending on the `mode` specified. By default,
 * it fetches as both associative and numeric (PGSQL_BOTH). Using PGSQL_ASSOC will fetch as an
 * associative array, and PGSQL_NUM will fetch as a numeric array. It returns NULL when there are
 * no more rows to fetch.
 *
 * This function calls the pg_fetch_array() function to fetch the next row from a Postgres result set
 * and trims any leading or trailing whitespace from each of the values.
 *
 * @param resource $result  The result resource returned by a Postgres query.
 * @param int $mode The type of array that should be produced from the current row data.
 * @return array|bool       An array of the next row in the result set, or false if there are no more rows.
 */
function wpsqli_fetch_array($result, $mode = PGSQL_BOTH)
{
    // Fetch the next row as an array
    $res = pg_fetch_array($result, null, $mode);

    // Check if the result is an array and trim its values
    if (is_array($res)) {
        foreach ($res as $v => $k) {
            $res[$v] = trim($k);
        }
    }

    // Return the trimmed array or false if there are no more rows
    return $res;
}

/**
 * Fetches a result row as an object.
 *
 * This function is a wrapper for the pg_fetch_object function. It retrieves the current row
 * of a result set as an object where the attributes correspond to the fetched row's column names.
 * This function can instantiate an object of a specified class, and pass parameters to its constructor,
 * allowing for custom objects based on the rows of the result set. If no class is specified, it defaults
 * to a stdClass object. If the class does not exist or the specified class's constructor requires more
 * arguments than are given, an exception is thrown.
 *
 * @param \PgSql\Result $result The result set returned by pg_query, pg_store_result
 *                              or pg_use_result.
 * @param string $class The name of the class to instantiate, set the properties of which
 *                      correspond to the fetched row's column names.
 * @param array $constructor_args An optional array of parameters to pass to the constructor
 *                                for the class name defined by the class parameter.
 * @return object|false An instance of the specified class with property names that correspond
 *                      to the column names returned in the result set, or FALSE on failure.
 */
function wpsqli_fetch_object($result, $class = "stdClass", $constructor_args = [])
{
    return pg_fetch_object($result, null, $class, $constructor_args);
}

/**
 * Fetches one row of data from the result set and returns it as an enumerated array.
 * Each call to this function will retrieve the next row in the result set, so it's typically
 * used in a loop to process multiple rows.
 *
 * This function is particularly useful when you need to retrieve a row as a simple array
 * where each column is accessed by an integer index starting at 0. It does not include
 * column names as keys, which can be marginally faster and less memory intensive than
 * associative arrays if the column names are not required.
 *
 * @param \PgSql\Result $result The result set returned by a query against the database.
 *
 * @return array|null Returns an enumerated array of strings representing the fetched row,
 * or NULL if there are no more rows in the result set.
 */
function wpsqli_fetch_row($result): ?array
{
    return pg_fetch_row($result);
}

/**
 * Adjusts the result pointer to an arbitrary row in the result set represented by the
 * $result object. This function can be used in conjunction with pg_fetch_row(),
 * pg_fetch_assoc(), pg_fetch_array(), or pg_fetch_object() to navigate between
 * rows in result sets, especially when using buffered result sets.
 *
 * This is an important function for situations where you need to access a specific row
 * directly without iterating over all preceding rows, which can be useful for pagination
 * or when looking up specific rows by row number.
 *
 * @param \PgSql\Result $result The result set returned by a query against the database.
 * @param int $row_number The desired row number to seek to. Row numbers are zero-indexed.
 *
 * @return bool Returns TRUE on success or FALSE on failure. If the row number is out of range,
 * it returns FALSE.
 */
function wpsqli_data_seek($result, int $row_number): bool
{
    return pg_result_seek($result, $row_number);
}

/**
 * Returns the next field in the result set.
 *
 * This function is a wrapper for the pg_fetch_field function, which retrieves information about
 * the next field in the result set represented by the `$result` parameter. It can be used in a loop
 * to obtain information about each field in the result set, such as name, table, max length, flags,
 * and type. This is useful for dynamically generating table structures or processing query results
 * when the structure of the result set is not known in advance or changes.
 *
 * @param \PgSql\Result $result The result set returned by pg_query, pg_store_result
 *                              or pg_use_result.
 * @return object An object which contains field definition information or FALSE if no field information
 *                is available.
 */
function wpsqli_fetch_field($result)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_fetch_field => pg_field_table (resource $result, int $field_number, bool $oid_only = false): mixed
    // Returns the name or oid of the table of the field. There's no direct function to mimic mysqli_fetch_field completely.
    //pg_field_table($result, $field_number);
}

/**
 * Gets the number of fields in a result set.
 *
 * This function is a wrapper for the pg_num_fields function. It returns the number
 * of fields (columns) in a result set. This is particularly useful when you need to
 * dynamically process a query result without knowing the schema of the returned data,
 * as it allows the script to iterate over all fields in each row of the result set.
 *
 * @param \PgSql\Result $result The result set returned by pg_query, pg_store_result
 *                              or pg_use_result.
 * @return int The number of fields in the specified result set.
 */
function wpsqli_num_fields($result)
{
    // mysqli_num_fields => pg_num_fields (resource $result): int
    // Returns the number of fields (columns) in a result.
    return pg_num_fields($result);
}

/**
 * Returns the number of columns for the most recent query on the connection.
 *
 * This function is a wrapper for the pg_field_count function. It retrieves the number of
 * columns obtained from the most recent query executed on the given database connection. This
 * can be particularly useful when you need to know how many columns will be returned by a
 * SELECT statement before fetching data, which can help in dynamically processing result sets.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return int An integer representing the number of fields in the result set.
 */
function wpsqli_field_count(&$connection)
{
    // mysqli_field_count => pg_num_fields (resource $result): int
    // Use pg_num_fields to get the number of fields (columns) in a result.
    return pg_num_fields($result);
}

/**
 * Transfers a result set from the last query.
 *
 * This function is a wrapper for the pg_store_result function. It is used to transfer the
 * result set from the last query executed on the given connection, which used the pg_STORE_RESULT
 * flag. This function must be called after executing a query that returns a result set (like SELECT).
 * It allows the complete result set to be transferred to the client and then utilized via the
 * pg_fetch_* functions. It's particularly useful when the result set is expected to be accessed
 * multiple times.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return \PgSql\Result|false A buffered result object or FALSE if an error occurred.
 */
function wpsqli_store_result(&$connection)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_store_result => Not needed in PostgreSQL.
    // PostgreSQL's pg_query automatically stores the results without a separate call.
    //return true;
}

/**
 * Initiates the retrieval of a result set from the last query executed using the pg_USE_RESULT mode.
 *
 * This function is a wrapper for the pg_use_result function. It is used to initiate the retrieval
 * of a result set from the last query executed on the given connection, without storing the entire result
 * set in the buffer. This is particularly useful for handling large result sets that could potentially
 * exceed the available PHP memory. The data is fetched row-by-row, reducing the immediate memory footprint.
 * However, it requires the connection to remain open, and no other operations can be performed on the
 * connection until the result set is fully processed.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return \PgSql\Result|false An unbuffered result object or FALSE if an error occurred.
 */
function wpsqli_use_result(&$connection)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_use_result => Not needed in PostgreSQL.
    // PostgreSQL does not differentiate between unbuffered and buffered queries like MySQL does.
}

/**
 * Frees the memory associated with a result.
 *
 * This function is a wrapper for the pg_free_result function. It's used to free the memory
 * allocated for a result set obtained from a query. When the result data is not needed anymore,
 * it's a good practice to free the associated resources, especially when dealing with large
 * datasets that can consume significant amounts of memory. It is an important aspect of resource
 * management and helps to keep the application's memory footprint minimal.
 *
 * @param \PgSql\Result $result The result set returned by pg_query, pg_store_result
 *                              or pg_use_result.
 * @return void This function doesn't return any value.
 */
function wpsqli_free_result($result)
{
    // mysqli_free_result => pg_free_result (resource $result): bool
    // Frees memory associated with a result.
    return pg_free_result($result);
}

/**
 * Checks if there are any more result sets from a multi query.
 *
 * mysqli_more_results => No direct equivalent in PostgreSQL.
 * PostgreSQL does not support multiple results like MySQL's multi_query function.
 * It returns TRUE if one or more result sets are available from the previous calls to
 * pg_multi_query(), otherwise FALSE.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return bool Returns TRUE if there are more result sets from previous multi queries and
 *              FALSE otherwise.
 */
function wpsqli_more_results(&$connection)
{
    // mysqli_more_results => No direct equivalent in PostgreSQL.
    // PostgreSQL does not have a built-in function to check for more results from a batch of queries.
    return false;
}

/**
 * Moves the internal result pointer to the next result set returned from a multi query.
 *
 * mysqli_next_result => No direct equivalent in PostgreSQL.
 * PostgreSQL does not support multiple results like MySQL's multi_query function.
 * FALSE if there are no more result sets, or FALSE with an error if there is a problem moving the result pointer.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return bool Returns TRUE on success or FALSE on failure (no more results or an error occurred).
 */
function wpsqli_next_result(&$connection)
{
    // mysqli_next_result => No direct equivalent in PostgreSQL.
    // PostgreSQL does not support multiple results like MySQL's multi_query function.
    return false;
}

/**
* Utility Functions
*/

function wpsqli_is_resource($object)
{
    return $object !== false && $object !== null;
}

/**
 * Gets the number of affected rows in the previous PostgreSQL operation.
 *
 * This function is a wrapper for the pg_affected_rows function, which is used to determine
 * the number of rows affected by the last INSERT, UPDATE, REPLACE or DELETE query executed on
 * the given connection. It is an important function for understanding the impact of such queries,
 * allowing the developer to verify that the expected number of rows were altered. It returns an
 * integer indicating the number of rows affected or -1 if the last query failed.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return int The number of affected rows in the previous operation, or -1 if the last operation failed.
 */
function wpsqli_affected_rows(&$connection)
{
    $result = $GLOBALS['pg4wp_result'];
    // mysqli_affected_rows => pg_affected_rows (resource $result): int
    // Returns the number of rows affected by INSERT, UPDATE, or DELETE query.
    return pg_affected_rows($result);
}

// Gets the list of sequences from postgres
function wpsqli_get_list_of_sequences(&$connection)
{
    $sql = "SELECT sequencename FROM pg_sequences";
    $result = pg_query($connection, $sql);
    if(!$result) {
        if (PG4WP_DEBUG || PG4WP_LOG) {
            $log = "Unable to get list of sequences\n";
            error_log($log, 3, PG4WP_LOG . 'pg4wp_errors.log');
        }
        return [];
    }

    $data = pg_fetch_all($result);
    return array_column($data, 'sequencename');
}

// Get the primary sequence for a table
function wpsqli_get_primary_sequence_for_table(&$connection, $table)
{
    // TODO: it should be possible to use a WP transient here for object caching
    global $sequence_lookup;
    if (empty($sequence_lookup)) {
        $sequence_lookup = [];
    }

    if (isset($sequence_lookup[$table])) {
        return $sequence_lookup[$table];
    }

    $sequences = wpsqli_get_list_of_sequences($connection);
    foreach($sequences as $sequence) {
        if (strncmp($sequence, $table, strlen($table)) === 0) {
            $sequence_lookup[$table] = $sequence;
            return $sequence;
        }
    }

    // we didn't find a sequence for this table.
    return null;
}

/**
 * Fetches the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
 *
 * @param resource|null $connection A PostgreSQL connection resource. Default is `null`.
 *
 * @return mixed The ID generated for an AUTO_INCREMENT column by the previous INSERT query on success; `false` on failure.
 *
 * Note:
 * 1. In PostgreSQL, this function uses CURRVAL() on the appropriate sequence to get the last inserted ID.
 * 2. In MySQL, last inserted ID is generally fetched using mysql_insert_id() or mysqli_insert_id().
 */
function wpsqli_insert_id(&$connection = null)
{
    global $wpdb;
    $data = null;
    $ins_field = $GLOBALS['pg4wp_ins_field'];
    $table = $GLOBALS['pg4wp_ins_table'];

    if($GLOBALS['pg4wp_ins_id']) {
        return $GLOBALS['pg4wp_ins_id'];
    } elseif(empty($sql)) {
        $sql = 'NO QUERY';
        $data = 0;
    } else {
        $seq = wpsqli_get_primary_sequence_for_table($connection, $table);
        $lastq = $GLOBALS['pg4wp_last_insert'];
        // Double quoting is needed to prevent seq from being lowercased automatically
        $sql = "SELECT CURRVAL('\"$seq\"')";
        $res = pg_query($connection, $sql);
        if (false !== $res) {
            $data = pg_fetch_result($res, 0, 0);
        } elseif (PG4WP_DEBUG || PG4WP_LOG) {
            $log = '[' . microtime(true) . "] wpsqli_insert_id() was called with '$table' and '$ins_field'" .
                    " and returned the error:\n" . pg_last_error($connection) .
                    "\nFor the query:\n" . $sql .
                    "\nThe latest INSERT query was :\n'$lastq'\n";
            error_log($log, 3, PG4WP_LOG . 'pg4wp_errors.log');
        }
    }

    if (PG4WP_DEBUG && $sql) {
        error_log('[' . microtime(true) . "] Getting inserted ID for '$table' ('$ins_field') : $sql => $data\n", 3, PG4WP_LOG . 'pg4wp_insertid.log');
    }

    $GLOBALS['pg4wp_conn'] = $connection;

    return $data;
}



/**
 * Sets the default character set to be used when sending data from and to the database server.
 *
 * This function is a wrapper for the pg_set_charset function. The pg_set_charset function
 * is used to set the character set to be used when sending data from and to the database server.
 * This is particularly important to ensure that data is properly encoded and decoded when stored
 * and retrieved from the database, avoiding character encoding issues.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param string $charset The desired character set.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_set_charset(&$connection, $charset)
{
    // mysqli_set_charset => pg_set_client_encoding (resource $connection, string $encoding): int
    // Sets the client encoding.
    return pg_set_client_encoding($connection, "UTF8");
}

/**
 * Escapes special characters in a string for use in an SQL statement.
 *
 * This function serves as a wrapper for the pg_real_escape_string function, which is
 * utilized to escape potentially dangerous special characters within a string. This is a
 * critical security measure to prevent SQL injection vulnerabilities by ensuring that user
 * input can be safely used in an SQL query. The function takes a string to be escaped and
 * the pg connection resource, and returns the escaped string which is safe to be included
 * in SQL statements.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @param string $string The string to be escaped.
 * @return string Returns the escaped string.
 */
function wpsqli_real_escape_string(&$connection, $string)
{
    // mysqli_real_escape_string => pg_escape_string (resource $connection, string $data): string
    // Escapes a string for safe use in database queries.
    return pg_escape_string($connection, $string);
}

/**
 * Retrieves the last error description for the most recent pg function call
 * that can succeed or fail.
 *
 * This function is a wrapper for the pg_last_error function, which returns a string
 * describing the error from the last PostgreSQL operation associated with the provided
 * connection resource. It's an essential function for debugging and error handling
 * in PostgreSQL-related operations. When a pg function fails, wpsqli_error can be
 * used to fetch the corresponding error message to understand what went wrong.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return string Returns a string with the error message for the most recent function call
 *                if it has failed, or an empty string if no error has occurred.
 */
function wpsqli_error(&$connection)
{
    return pg_last_error($connection);
}

/**
 * Returns the SQLSTATE error code for the last query executed on the connection.
 *
 * @param resource $connection  The Postgres database connection resource.
 *
 * @return string|false  SQLSTATE error code or false if no error.
 *
 * Note:
 * 1. This function uses `pg_get_result` to get the result resource of the last query.
 * 2. `pg_result_status` returns the status of the result.
 * 3. `pg_result_error_field` is used to get the SQLSTATE error code.
 * 4. In MySQL, you could use `mysqli_errno` to get the error code directly.
 */
function wpsqli_errno(&$connection)
{
    $result = pg_get_result($connection);
    if ($result === false) {
        return false;
    }

    $result_status = pg_result_status($result);
    return pg_result_error_field($result_status, PGSQL_DIAG_SQLSTATE);
}

/**
 * Enables or disables internal report functions.
 *
 * This function is a wrapper for the pg_report function, which is used to set the
 * reporting mode of pg errors. This is useful for defining whether errors should be
 * reported as exceptions, warnings, or silent (no report). It's important for configuring
 * the error reporting behavior of the pg extension to suit the needs of your application,
 * particularly in a development environment where more verbose error reporting is beneficial.
 *
 * @param int $flags A bit-mask constructed from the pg_REPORT_* constants.
 * @return bool Returns TRUE on success or FALSE on failure.
 */
function wpsqli_report($flags)
{
    // mysqli_report => No direct equivalent in PostgreSQL.
    // MySQL's mysqli_report function is used to set what MySQLi should report, which doesn't have a direct equivalent in PostgreSQL's PHP functions.
    return true;
}

/**
 * Retrieves information about the most recently executed query.
 *
 * This function is a wrapper for the pg_info function. It provides a string containing
 * information about the most recently executed query on the given connection resource. This
 * can include information such as the number of rows affected by an INSERT, UPDATE, REPLACE,
 * or DELETE query, as well as the number of rows matched and changed. It is valuable for
 * obtaining detailed insights into the execution of database operations.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return string|null A string representing information about the last query executed,
 *                     or NULL if no information is available.
 */
function wpsqli_info(&$connection)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_info => No direct equivalent in PostgreSQL.
    // This function retrieves information about the most recently executed query, which is not provided by PostgreSQL's PHP functions.
}


/**
 * Polls connections for results.
 *
 * This function is a wrapper for the pg_poll function. It can be used to poll multiple
 * connections to check if one or more of the connections have results available for client-side
 * processing. It is useful when you have multiple asynchronous queries running and need to handle
 * them as soon as their results become available. The function takes variable references for read,
 * error, and reject arrays, and modifies them to indicate which connections have results, which
 * have errors, and which were rejected respectively.
 *
 * @param array &$read Array of connections to check for outstanding results that can be read.
 * @param array &$error Array of connections on which an error occurred.
 * @param array &$reject Array of connections rejected because no asynchronous query
 *                       has been run on them.
 * @param int $sec Number of seconds to wait, must be non-negative.
 * @param int $usec Number of microseconds to wait, must be non-negative.
 * @return int|false Number of ready connections upon success, FALSE otherwise.
 */
function wpsqli_poll(&...$args)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_poll => No direct equivalent in PostgreSQL.
    // Polling for result availability is not a concept that is directly exposed in PostgreSQL's PHP functions.
    // Asynchronous query handling in PHP with PostgreSQL typically involves using separate processes or coroutines.
}

/**
 * Gets the result from asynchronous PostgreSQL query.
 *
 * This function is a wrapper for the pg_reap_async_query function. It is used after initiating
 * a query with pg_query() on a connection with the pg_ASYNC flag set. It retrieves the result
 * from the query once it is complete, which can be used with pg_poll() to manage multiple
 * asynchronous queries. It returns a pg_result object for successful SELECT queries, or TRUE for
 * other DML queries (INSERT, UPDATE, DELETE, etc.) if the operation was successful, or FALSE on failure.
 *
 * @param PgSql\Connection $connection The pg connection resource.
 * @return \PgSql\Result|bool A pg_result object for successful SELECT queries, TRUE for other
 *                            successful DML queries, or FALSE on failure.
 */
function wpsqli_reap_async_query(&$connection)
{
    throw new \Exception("PG4WP: Not Yet Implemented");
    // mysqli_reap_async_query => No direct equivalent in PostgreSQL.
    // Asynchronous queries can be executed in PostgreSQL using pg_send_query and retrieved using pg_get_result.
}


================================================
FILE: pg4wp/driver_pgsql_rewrite.php
================================================
<?php

// Autoload function to automatically require rewriter classes from the "rewriters" folder
spl_autoload_register(function ($className) {
    $filePath = PG4WP_ROOT . '/rewriters/' . $className . '.php';
    if (file_exists($filePath)) {
        require_once $filePath;
    }
});


function createSQLRewriter(string $sql): AbstractSQLRewriter
{
    $sql = trim($sql);
    if (preg_match('/^(SELECT|INSERT|REPLACE INTO|UPDATE|DELETE|DESCRIBE|ALTER TABLE|CREATE TABLE|DROP TABLE|SHOW INDEX|SHOW VARIABLES|SHOW TABLES|OPTIMIZE TABLE|SET NAMES|SHOW FULL COLUMNS|SHOW TABLE STATUS)\b/i', $sql, $matches)) {
        // Convert to a format suitable for class names (e.g., "SHOW TABLES" becomes "ShowTables")
        $type = str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($matches[1]))));
        $className = $type . 'SQLRewriter';

        if (class_exists($className)) {
            return new $className($sql);
        } else {
            throw new Exception("No class defined to handle SQL type: " . $type);
        }
    }
    throw new Exception("Invalid or unsupported SQL statement.");
}


function pg4wp_rewrite($sql)
{
    // Note:  Can be called from constructor before $wpdb is set
    global $wpdb;

    $initial = $sql;
    $logto = 'queries';
    // The end of the query may be protected against changes
    $end = '';

    $rewriter = createSQLRewriter(trim($sql));
    $sql = $rewriter->rewrite();
    $logto = strtoupper($rewriter->type());
    switch ($rewriter->type()) {
        case 'Update':
            // This will avoid modifications to anything following ' SET '
            list($sql, $end) = explode(' SET ', $sql, 2);
            $end = ' SET ' . $end;
            break;
        case 'Insert':
            // This will avoid modifications to anything following ' VALUES'
            list($sql, $end) = explode(' VALUES', $sql, 2);
            $end = ' VALUES' . $end;

            // When installing, the sequence for table terms has to be updated
            if(defined('WP_INSTALLING') && WP_INSTALLING && false !== strpos($sql, 'INSERT INTO `' . $wpdb->terms . '`')) {
                $end .= ';SELECT setval(\'' . $wpdb->terms . '_term_id_seq\', (SELECT MAX(term_id) FROM ' . $wpdb->terms . ')+1);';
            }
            break;
        case 'Insert':
            break;
        default:
    }

    $sql = correctMetaValue($sql);
    $sql = handleInterval($sql);
    $sql = cleanAndCapitalize($sql);
    $sql = correctEmptyInStatements($sql);
    $sql = correctQuoting($sql);

    // Put back the end of the query if it was separated
    $sql .= $end;

    // For insert ID caching
    if($logto == 'INSERT') {
        $pattern = '/INSERT INTO "?([\w_]+)"? \(([^)]+)\)/i';
        preg_match($pattern, $sql, $matches);

        if (isset($matches[1])) {
            $GLOBALS['pg4wp_ins_table'] = $matches[1];
        }

        if (isset($matches[2])) {
            $columns_str = $matches[2];
            $columns = explode(',', $columns_str);
            $columns = array_map(function ($column) {
                return trim(trim($column), '"');
            }, $columns);
            if (isset($columns[0])) {
                $GLOBALS['pg4wp_ins_field'] = $columns[0];
            }
        }

        $GLOBALS['pg4wp_last_insert'] = $sql;
    } elseif(isset($GLOBALS['pg4wp_queued_query'])) {
        pg_query($GLOBALS['pg4wp_queued_query']);
        unset($GLOBALS['pg4wp_queued_query']);
    }

    if(PG4WP_DEBUG) {
        if($initial != $sql) {
            error_log('[' . microtime(true) . "] Converting :\n$initial\n---- to ----\n$sql\n---------------------\n", 3, PG4WP_LOG . 'pg4wp_' . $logto . '.log');
        } else {
            error_log('[' . microtime(true) . "] $sql\n---------------------\n", 3, PG4WP_LOG . 'pg4wp_unmodified.log');
        }
    }
    return $sql;
}

/**
 * Correct the meta_value field for WP 2.9.1 and add type cast.
 *
 * @param string $sql SQL query string
 * @return string Modified SQL query string
 */
function correctMetaValue($sql)
{
    // WP 2.9.1 uses a comparison where text data is not quoted
    $sql = preg_replace('/AND meta_value = (-?\d+)/', 'AND meta_value = \'$1\'', $sql);
    // Add type cast for meta_value field when it's compared to number
    $sql = preg_replace('/AND meta_value < (\d+)/', 'AND meta_value::bigint < $1', $sql);
    return $sql;
}

/**
 * Handle interval expressions in SQL query.
 *
 * @param string $sql SQL query string
 * @return string Modified SQL query string
 */
function handleInterval($sql)
{
    // Generic "INTERVAL xx YEAR|MONTH|DAY|HOUR|MINUTE|SECOND" handler
    $sql = preg_replace('/INTERVAL[ ]+(\d+)[ ]+(YEAR|MONTH|DAY|HOUR|MINUTE|SECOND)/', "'\$1 \$2'::interval", $sql);
    // DATE_SUB handling
    $sql = preg_replace('/DATE_SUB[ ]*\(([^,]+),([^\)]+)\)/', '($1::timestamp - $2)', $sql);
    return $sql;
}

/**
 * Clean SQL query from illegal characters and handle capitalization.
 *
 * @param string $sql SQL query string
 * @return string Modified SQL query string
 */
function cleanAndCapitalize($sql)
{
    // Remove illegal characters
    $sql = str_replace('`', '', $sql);
    // Field names with CAPITALS need special handling
    if (false !== strpos($sql, 'ID')) {
        $patterns = [
            '/ID([^ ])/' => 'ID $1',
            '/ID$/' => 'ID ',
            '/\(ID/' => '( ID',
            '/,ID/' => ', ID',
            '/[0-9a-zA-Z_]+ID/' => '"$0"',
            '/\.ID/' => '."ID"',
            '/[\s]ID /' => ' "ID" ',
            '/"ID "/' => ' "ID" '
        ];
        foreach ($patterns as $pattern => $replacement) {
            $sql = preg_replace($pattern, $replacement, $sql);
        }
    }
    return $sql;
}

/**
 * Correct empty IN statements in SQL query.
 *
 * @param string $sql SQL query string
 * @return string Modified SQL query string
 */
function correctEmptyInStatements($sql)
{
    $search = ['IN (\'\')', 'IN ( \'\' )', 'IN ()'];
    $replace = 'IN (NULL)';
    $sql = str_replace($search, $replace, $sql);
    return $sql;
}

/**
 * Correct quoting for PostgreSQL 9.1+ compatibility.
 *
 * @param string $sql SQL query string
 * @return string Modified SQL query string
 */
function correctQuoting($sql)
{
    $sql = str_replace("\\'", "''", $sql);
    $sql = str_replace('\"', '"', $sql);
    return $sql;
}


================================================
FILE: pg4wp/rewriters/AbstractSQLRewriter.php
================================================
<?php

abstract class AbstractSQLRewriter
{
    protected string $originalSQL;

    public function __construct(string $sql)
    {
        $this->originalSQL = $sql;
    }

    abstract public function rewrite(): string;

    public function original(): string
    {
        return $this->originalSQL;
    }

    public function type(): string
    {
        // Get the called class name and remove the "SQLRewriter" suffix to get the SQL type
        $className = get_called_class();
        $type = str_replace('SQLRewriter', '', $className);
        return $type;
    }
}


================================================
FILE: pg4wp/rewriters/AlterTableSQLRewriter.php
================================================
<?php

class AlterTableSQLRewriter extends AbstractSQLRewriter
{
    private $stringReplacements = [
        ' tinytext'		=> ' text',
        ' mediumtext'	=> ' text',
        ' longtext'		=> ' text',
        ' unsigned'		=> ' ',
        'gmt datetime NOT NULL default \'0000-00-00 00:00:00\''	=> 'gmt timestamp NOT NULL DEFAULT timezone(\'gmt\'::text, now())',
        'default \'0000-00-00 00:00:00\''	=> 'DEFAULT now()',
        '\'0000-00-00 00:00:00\''	=> 'now()',
        ' datetime'		=> ' timestamp',
        ' DEFAULT CHARACTER SET utf8mb4' => '',
        ' DEFAULT CHARACTER SET utf8'	=> '',

        // For WPMU (starting with WP 3.2)
        " enum('0','1')"	=> ' smallint',
        ' COLLATE utf8mb4_unicode_520_ci'	=> '',
        ' COLLATE utf8_general_ci'	=> '',
        ' CHARACTER SET utf8' => '',
        ' DEFAULT CHARSET=utf8' => '',

        // For flash-album-gallery plugin
        ' tinyint'		=> ' smallint'
    ];

    public function rewrite(): string
    {
        $sql = $this->original();
        
        $sql = $this->rewrite_numeric_type($sql);
        $sql = $this->rewrite_columns_with_protected_names($sql);

        if (str_contains($sql, 'ADD INDEX') || str_contains($sql, 'ADD UNIQUE INDEX')) {
            $sql = $this->rewriteAddIndex($sql);
            return $sql;
        }
        if (str_contains($sql, 'CHANGE COLUMN')) {
            $sql = $this->rewriteChangeColumn($sql);
            return $sql;
        }
        if (str_contains($sql, 'ALTER COLUMN')) {
            $sql = $this->rewriteAlterColumn($sql);
            return $sql;
        }
        if (str_contains($sql, 'ADD COLUMN')) {
            $sql = $this->rewriteAddColumn($sql);
            return $sql;
        }
        if (str_contains($sql, 'ADD KEY') || str_contains($sql, 'ADD UNIQUE KEY')) {
            $sql = $this->rewriteAddKey($sql);
            return $sql;
        }
        if (str_contains($sql, 'DROP INDEX')) {
            $sql = $this->rewriteDropIndex($sql);
            return $sql;
        }
        if (str_contains($sql, 'DROP PRIMARY KEY')) {
            $sql = $this->rewriteDropPrimaryKey($sql);
            return $sql;
        }

        return $sql;
    }

    private function rewriteAddIndex(string $sql): string
    {
        $pattern = '/ALTER TABLE\s+(\w+)\s+ADD (UNIQUE |)INDEX\s+([^\s]+)\s+\(((?:[^\(\)]+|\([^\(\)]+\))+)\)/';

        if(1 === preg_match($pattern, $sql, $matches)) {
            $table = $matches[1];
            $unique = $matches[2];
            $index = $matches[3];
            $columns = $matches[4];

            // Remove prefix indexing
            // Rarely used and apparently unnecessary for current uses
            $columns = preg_replace('/\([^\)]*\)/', '', $columns);

            // Workaround for index name duplicate
            $index = $table . '_' . $index;

            // Add backticks around index name and column name, and include IF NOT EXISTS clause
            $sql = "CREATE {$unique}INDEX IF NOT EXISTS `{$index}` ON `{$table}` (`{$columns}`)";
        }

        return $sql;
    }

    private function rewriteChangeColumn(string $sql): string
    {
        $pattern = '/ALTER TABLE\s+(\w+)\s+CHANGE COLUMN\s+([^\s]+)\s+([^\s]+)\s+([^ ]+)( unsigned|)\s*(NOT NULL|)\s*(default (.+)|)/';

        if(1 === preg_match($pattern, $sql, $matches)) {
            $table = $matches[1];
            $col = $matches[2];
            $newname = $matches[3];
            $type = strtolower($matches[4]);
            if(isset($this->stringReplacements[$type])) {
                $type = $this->stringReplacements[$type];
            }
            $unsigned = $matches[5];
            $notnull = $matches[6];
            $default = $matches[7];
            $defval = $matches[8];
            if(isset($this->stringReplacements[$defval])) {
                $defval = $this->stringReplacements[$defval];
            }
            $newq = "ALTER TABLE $table ALTER COLUMN $col TYPE $type";
            if(!empty($notnull)) {
                $newq .= ", ALTER COLUMN $col SET NOT NULL";
            }
            if(!empty($default)) {
                $newq .= ", ALTER COLUMN $col SET DEFAULT $defval";
            }
            if($col != $newname) {
                $newq .= ";ALTER TABLE $table RENAME COLUMN $col TO $newcol;";
            }
            $sql = $newq;
        }

        return $sql;
    }

    private function rewriteAlterColumn(string $sql): string
    {
        $pattern = '/ALTER TABLE\s+(\w+)\s+ALTER COLUMN\s+/';

        if(1 === preg_match($pattern, $sql)) {
            // Translate default values
            $sql = str_replace(
                array_keys($this->stringReplacements),
                array_values($this->stringReplacements),
                $sql
            );
        }

        return $sql;
    }

    private function rewriteAddColumn(string $sql): string
    {
        $pattern = '/ALTER TABLE\s+(\w+)\s+ADD COLUMN\s+([^\s]+)\s+([^ ]+)( unsigned|)\s+(NOT NULL|)\s*(default (.+)|)/';

        if(1 === preg_match($pattern, $sql, $matches)) {
            $table = $matches[1];
            $col = $matches[2];
            $type = strtolower($matches[3]);
            if(isset($this->stringReplacements[$type])) {
                $type = $this->stringReplacements[$type];
            }
            $unsigned = $matches[4];
            $notnull = $matches[5];
            $default = $matches[6];
            $defval = $matches[7];
            if(isset($this->stringReplacements[$defval])) {
                $defval = $this->stringReplacements[$defval];
            }
            $newq = "ALTER TABLE $table ADD COLUMN $col $type";
            if(!empty($default)) {
                $newq .= " DEFAULT $defval";
            }
            if(!empty($notnull)) {
                $newq .= " NOT NULL";
            }
            $sql = $newq;
        }

        return $sql;
    }

    private function rewriteAddKey(string $sql): string
    {
        $pattern = '/ALTER TABLE\s+(\w+)\s+ADD (UNIQUE |)KEY\s+([^\s]+)\s+\(((?:[^\(\)]+|\([^\(\)]+\))+)\)/';

        if(1 === preg_match($pattern, $sql, $matches)) {
            $table = $matches[1];
            $unique = $matches[2];
            $index = $matches[3];
            $columns = $matches[4];

            // Remove prefix indexing
            // Rarely used and apparently unnecessary for current uses
            $columns = preg_replace('/\([^\)]*\)/', '', $columns);

            // Workaround for index name duplicate
            $index = $table . '_' . $index;
            $sql = "CREATE {$unique}INDEX $index ON $table ($columns)";
        }

        return $sql;
    }

    private function rewriteDropIndex(string $sql): string
    {
        $pattern = '/ALTER TABLE\s+(\w+)\s+DROP INDEX\s+([^\s]+)/';

        if(1 === preg_match($pattern, $sql, $matches)) {
            $table = $matches[1];
            $index = $matches[2];
            $sql = "DROP INDEX {$table}_{$index}";
        }

        return $sql;
    }

    private function rewriteDropPrimaryKey(string $sql): string
    {
        $pattern = '/ALTER TABLE\s+(\w+)\s+DROP PRIMARY KEY/';

        if(1 === preg_match($pattern, $sql, $matches)) {
            $table = $matches[1];
            $sql = "ALTER TABLE {$table} DROP CONSTRAINT {$table}_pkey";
        }

        return $sql;
    }

    private function rewrite_numeric_type($sql)
    {
        // Numeric types in MySQL which need to be rewritten
        $numeric_types = ["bigint", "int", "integer", "smallint", "mediumint", "tinyint", "double", "decimal"];
        $numeric_types_imploded = implode('|', $numeric_types);

        // Prepare regex pattern to match 'type(x)'
        $pattern = "/(" . $numeric_types_imploded . ")\(\d+\)/";

        // Execute type find & replace
        $sql = preg_replace_callback($pattern, function ($matches) {
            return $matches[1];
        }, $sql);

        // bigint
        $pattern = '/bigint(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i';
        preg_match($pattern, $sql, $matches);
        if($matches) {
            $sql = preg_replace($pattern, 'bigserial', $sql);
        }

        // int
        $pattern = '/int(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i';
        preg_match($pattern, $sql, $matches);
        if($matches) {
            $sql = preg_replace($pattern, 'serial', $sql);
        }

        // smallint
        $pattern = '/smallint(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i';
        preg_match($pattern, $sql, $matches);
        if($matches) {
            $sql = preg_replace($pattern, 'smallserial', $sql);
        }

        // Handle for numeric and decimal -- being replaced with serial
        $numeric_patterns = ['/numeric(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i', '/decimal(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i'];
        foreach($numeric_patterns as $pattern) {
            preg_match($pattern, $sql, $matches);
            if($matches) {
                $sql = preg_replace($pattern, 'serial', $sql);
            }
        }

        return $sql;
    }

    private function rewrite_columns_with_protected_names($sql) 
    {
        // Splitting the SQL statement into parts before "(", inside "(", and after ")"
        if (preg_match('/^(CREATE TABLE IF NOT EXISTS|CREATE TABLE|ALTER TABLE)\s+([^\s]+)\s*\((.*)\)(.*)$/is', $sql, $matches)) {
            $prefix = $matches[1] . ' ' . $matches[2] . ' (';
            $columnsAndKeys = $matches[3];
            $suffix = ')' . $matches[4];
    
            $regex = '/(?:^|\s*,\s*)(\b(?:timestamp|date|time|default)\b)\s*(?=\s+\w+)/i'; 

            // Callback function to add quotes around protected column names
            $callback = function($matches) {
                $whitespace = str_replace($matches[1], "", $matches[0]);
                return $whitespace . '"' . $matches[1] . '"';
            };

            // Replace protected column names with quoted versions within columns and keys part
            $columnsAndKeys = preg_replace_callback($regex, $callback, $columnsAndKeys);
            return $prefix . $columnsAndKeys . $suffix;
        }

        return $sql;
    }
}


================================================
FILE: pg4wp/rewriters/CreateTableSQLRewriter.php
================================================
<?php

class CreateTableSQLRewriter extends AbstractSQLRewriter
{
    private $stringReplacements = [
        ' tinytext'		=> ' text',
        ' mediumtext'	=> ' text',
        ' longtext'		=> ' text',
        ' unsigned'		=> ' ',
        'gmt datetime NOT NULL default \'0000-00-00 00:00:00\''	=> 'gmt timestamp NOT NULL DEFAULT timezone(\'gmt\'::text, now())',
        'default \'0000-00-00 00:00:00\''	=> 'DEFAULT now()',
        '\'0000-00-00 00:00:00\''	=> 'now()',
        ' datetime'		=> ' timestamp',
        ' DEFAULT CHARACTER SET utf8mb4' => '',
        ' DEFAULT CHARACTER SET utf8'	=> '',

        // For WPMU (starting with WP 3.2)
        " enum('0','1')"	=> ' smallint',
        ' COLLATE utf8mb4_unicode_520_ci'	=> '',
        ' COLLATE utf8_general_ci'	=> '',
        ' CHARACTER SET utf8' => '',
        ' DEFAULT CHARSET=utf8' => '',

        ' tinyint'		=> ' smallint',
        ' mediumint'    => ' integer'
    ];

    public function rewrite(): string
    {
        $sql = $this->original();

        $tableSQL = str_replace('CREATE TABLE IF NOT EXISTS ', 'CREATE TABLE ', $sql);
        $pattern = '/CREATE TABLE [`]?(\w+)[`]?/';
        preg_match($pattern, $tableSQL, $matches);
        $table = $matches[1];

        // change all creates into create if not exists
        $pattern = "/CREATE TABLE (IF NOT EXISTS )?(\w+)\s*\(/i";
        $replacement = 'CREATE TABLE IF NOT EXISTS $2 (';
        $sql = preg_replace($pattern, $replacement, $sql);

        // Remove trailing spaces
        $sql = trim($sql);

        // Add a slash if needed
        if (substr($sql, strlen($sql) - 1, 1) != ";") {
            $sql = $sql . ";";
        }

        // Translate types and some other replacements
        $sql = str_ireplace(
            array_keys($this->stringReplacements),
            array_values($this->stringReplacements),
            $sql
        );

        $sql = $this->rewrite_numeric_type($sql);
        $sql = $this->rewrite_columns_with_protected_names($sql);

        // Support for UNIQUE INDEX creation
        $pattern = '/,\s*(UNIQUE |)KEY\s+(`[^`]+`|\w+)\s+\(((?:[^()]|\([^)]*\))*)\)/';
        if(preg_match_all($pattern, $sql, $matches, PREG_SET_ORDER)) {
            foreach($matches as $match) {
                $unique = $match[1];
                $index = $match[2];
                $columns = $match[3];

                // Removing backticks from the index names
                $index = str_replace('`', '', $index);

                // Removing backticks and key length constraints from the columns
                $columns = preg_replace(["/`/", "/\(\d+\)/"], '', $columns);

                // Creating a unique index name
                $indexName = $table . '_' . $index;

                // Appending the CREATE INDEX statement to SQL
                $sql .= "\nCREATE {$unique}INDEX IF NOT EXISTS $indexName ON $table ($columns);";
            }
        }
        // Now remove handled indexes
        $sql = preg_replace($pattern, '', $sql);


        // Rewrite unique keys to just be UNIQUE without a key name
        $pattern = "/(,\s*)?UNIQUE KEY\s+[a-zA-Z0-9_]+\s+(\([a-zA-Z0-9_,\s]+\))/";
        $replacement = "$1UNIQUE $2";
        $sql = preg_replace($pattern, $replacement, $sql);

        // Rewrite Primary keys to not have a key name
        $pattern = '/PRIMARY KEY\s+\w+\s*\((.*?)\)/';
        $replacement = 'PRIMARY KEY ($1)';
        $sql = preg_replace($pattern, $replacement, $sql);

        return $sql;
    }

    private function rewrite_numeric_type($sql)
    {
        // Numeric types in MySQL which need to be rewritten
        $numeric_types = ["bigint", "int", "integer", "smallint", "mediumint", "tinyint", "double", "decimal"];
        $numeric_types_imploded = implode('|', $numeric_types);

        // Prepare regex pattern to match 'type(x)'
        $pattern = "/(" . $numeric_types_imploded . ")\(\d+\)/i";

        // Execute type find & replace
        $sql = preg_replace_callback($pattern, function ($matches) {
            return $matches[1];
        }, $sql);

        // bigint
        $pattern = '/bigint(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i';
        preg_match($pattern, $sql, $matches);
        if($matches) {
            $sql = preg_replace($pattern, 'bigserial', $sql);
        }

        // int
        $pattern = '/int(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i';
        preg_match($pattern, $sql, $matches);
        if($matches) {
            $sql = preg_replace($pattern, 'serial', $sql);
        }

        // smallint
        $pattern = '/smallint(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i';
        preg_match($pattern, $sql, $matches);
        if($matches) {
            $sql = preg_replace($pattern, 'smallserial', $sql);
        }

        // Handle for numeric and decimal -- being replaced with serial
        $numeric_patterns = ['/numeric(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i', '/decimal(\(\d+\))?([ ]*NOT NULL)?[ ]*auto_increment/i'];
        foreach($numeric_patterns as $pattern) {
            preg_match($pattern, $sql, $matches);
            if($matches) {
                $sql = preg_replace($pattern, 'serial', $sql);
            }
        }

        return $sql;
    }

    private function rewrite_columns_with_protected_names($sql) 
    {
        // Splitting the SQL statement into parts before "(", inside "(", and after ")"
        if (preg_match('/^(CREATE TABLE IF NOT EXISTS|CREATE TABLE|ALTER TABLE)\s+([^\s]+)\s*\((.*)\)(.*)$/is', $sql, $matches)) {
            $prefix = $matches[1] . ' ' . $matches[2] . ' (';
            $columnsAndKeys = $matches[3];
            $suffix = ')' . $matches[4];
    
            $regex = '/(?:^|\s*,\s*)(\b(?:timestamp|date|time|default|end)\b)\s*(?=\s+\w+)/i'; 

            // Callback function to add quotes around protected column names
            $callback = function($matches) {
                $whitespace = str_replace($matches[1], "", $matches[0]);
                return $whitespace . '"' . $matches[1] . '"';
            };

            // Replace protected column names with quoted versions within columns and keys part
            $columnsAndKeys = preg_replace_callback($regex, $callback, $columnsAndKeys);
            return $prefix . $columnsAndKeys . $suffix;
        }

        return $sql;
    }
}


================================================
FILE: pg4wp/rewriters/DeleteSQLRewriter.php
================================================
<?php

class DeleteSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        global $wpdb;

        $sql = $this->original();

        // ORDER BY is not supported in DELETE queries, and not required
        // when LIMIT is not present
        if(false !== strpos($sql, 'ORDER BY') && false === strpos($sql, 'LIMIT')) {
            $pattern = '/ORDER BY \S+ (ASC|DESC)?/';
            $sql = preg_replace($pattern, '', $sql);
        }

        // LIMIT is not allowed in DELETE queries
        $sql = str_replace('LIMIT 1', '', $sql);
        $sql = str_replace(' REGEXP ', ' ~ ', $sql);

        // Get the WordPress table prefix
        $prefix = $wpdb->prefix;

        // This handles removal of duplicate entries in table options
        if(false !== strpos($sql, 'DELETE o1 FROM ')) {
            $sql = "DELETE FROM $wpdb->options WHERE option_id IN " .
                "(SELECT o1.option_id FROM $wpdb->options AS o1, $wpdb->options AS o2 " .
                "WHERE o1.option_name = o2.option_name " .
                "AND o1.option_id < o2.option_id)";
        }
        // Rewrite _transient_timeout multi-table delete query with dynamic prefix for options table
        elseif(preg_match('/DELETE a, b FROM ' . preg_quote($prefix, '/') . 'options a, ' . preg_quote($prefix, '/') . 'options b/', $sql)) {
            $where = substr($sql, strpos($sql, 'WHERE ') + 6);
            $where = rtrim($where, " \t\n\r;");
            // Fix string/number comparison by adding check and cast
            $where = str_replace('AND b.option_value', 'AND b.option_value ~ \'^[0-9]+$\' AND CAST(b.option_value AS BIGINT)', $where);
            // Mirror WHERE clause to delete both sides of self-join.
            $where2 = strtr($where, array('a.' => 'b.', 'b.' => 'a.'));
            $sql = "DELETE FROM {$wpdb->options} a USING {$wpdb->options} b WHERE " .
                '(' . $where . ') OR (' . $where2 . ');';
        }

        // Rewrite _transient_timeout multi-table delete query with dynamic prefix for sitemeta table
        elseif(preg_match('/DELETE a, b FROM ' . preg_quote($prefix, '/') . 'sitemeta a, ' . preg_quote($prefix, '/') . 'sitemeta b/', $sql)) {
            $where = substr($sql, strpos($sql, 'WHERE ') + 6);
            $where = rtrim($where, " \t\n\r;");
            // Fix string/number comparison by adding check and cast
            $where = str_replace('AND b.meta_value', 'AND b.meta_value ~ \'^[0-9]+$\' AND CAST(b.meta_value AS BIGINT)', $where);
            // Mirror WHERE clause to delete both sides of self-join.
            $where2 = strtr($where, array('a.' => 'b.', 'b.' => 'a.'));
            // Use $wpdb's sitemeta table name which should already have the correct prefix
            if(isset($wpdb->sitemeta)) {
                $sql = "DELETE FROM {$wpdb->sitemeta} a USING {$wpdb->sitemeta} b WHERE " .
                    '(' . $where . ') OR (' . $where2 . ');';
            } else {
                // Fallback if $wpdb->sitemeta is not available
                $sql = "DELETE FROM {$prefix}sitemeta a USING {$prefix}sitemeta b WHERE " .
                    '(' . $where . ') OR (' . $where2 . ');';
            }
        }
        
        // Add a more general pattern to handle multi-table DELETE with aliases and dynamic table names
        elseif(preg_match('/DELETE\s+([a-zA-Z0-9_]+),\s*([a-zA-Z0-9_]+)\s+FROM\s+([a-zA-Z0-9_' . preg_quote($prefix, '/') . ']+)\s+([a-zA-Z0-9_]+),\s*([a-zA-Z0-9_' . preg_quote($prefix, '/') . ']+)\s+([a-zA-Z0-9_]+)\s+WHERE/i', $sql, $matches)) {
            // Extract aliases and table names
            $firstAlias = $matches[1];
            $secondAlias = $matches[2];
            $firstTable = $matches[3];
            $firstTableAlias = $matches[4];
            $secondTable = $matches[5];
            $secondTableAlias = $matches[6];
            
            // Extract WHERE clause
            $where = substr($sql, strpos($sql, 'WHERE ') + 6);
            $where = rtrim($where, " \t\n\r;");
            
            // Check if the table names are known WordPress tables and replace with dynamic property references
            foreach([$firstTable, $secondTable] as $index => $tableName) {
                // Strip prefix if it exists to get the base table name
                $baseTableName = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $tableName);
                
                // Check if $wpdb has a property for this table
                if(isset($wpdb->$baseTableName)) {
                    // Replace the hardcoded table name with the dynamic property
                    if($index === 0) {
                        $firstTable = $wpdb->$baseTableName;
                    } else {
                        $secondTable = $wpdb->$baseTableName;
                    }
                }
            }
            
            // Generate PostgreSQL DELETE...USING syntax
            $sql = "DELETE FROM $firstTable $firstTableAlias USING $secondTable $secondTableAlias WHERE $where;";
        }

        // Akismet sometimes doesn't write 'comment_ID' with 'ID' in capitals where needed ...
        if(false !== strpos($sql, $wpdb->comments)) {
            $sql = str_replace(' comment_id ', ' comment_ID ', $sql);
        }

        return $sql;
    }
}


================================================
FILE: pg4wp/rewriters/DescribeSQLRewriter.php
================================================
<?php

class DescribeSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        $sql = $this->original();
        $table = $this->extractTableName($sql);
        return $this->generatePostgresDescribeTable($table);
    }

    /**
     * Extracts table name from a "DESCRIBE" SQL statement.
     *
     * @param string $sql The SQL statement
     * @return string|null The table name if found, or null otherwise
     */
    protected function extractTableName($sql)
    {
        $pattern = "/DESCRIBE ['\"`]?([^'\"`]+)['\"`]?/i";
        if (preg_match($pattern, $sql, $matches)) {
            return $matches[1];
        }
        return null;
    }

    /**
     * Generates a PostgreSQL-compatible SQL query to mimic MySQL's "DESCRIBE".
     *
     * @param string $tableName The table name
     * @param string $schema The schema name
     * @return string The generated SQL query
     */
    public function generatePostgresDescribeTable($tableName, $schema = "public")
    {
        $sql = <<<SQL
            SELECT  
                f.attnum AS number,  
                f.attname AS name,  
                f.attnum,  
                f.attnotnull AS notnull,  
                pg_catalog.format_type(f.atttypid,f.atttypmod) AS type,  
                CASE  
                    WHEN p.contype = 'p' THEN 't'  
                    ELSE 'f'  
                END AS primarykey,  
                CASE  
                    WHEN p.contype = 'u' THEN 't'  
                    ELSE 'f'
                END AS uniquekey,
                CASE
                    WHEN p.contype = 'f' THEN g.relname
                END AS foreignkey,
                CASE
                    WHEN p.contype = 'f' THEN p.confkey
                END AS foreignkey_fieldnum,
                CASE
                    WHEN p.contype = 'f' THEN g.relname
                END AS foreignkey,
                CASE
                    WHEN p.contype = 'f' THEN p.conkey
                END AS foreignkey_connnum,
                CASE
                    WHEN f.atthasdef = 't' THEN pg_get_expr(d.adbin, d.adrelid)
                END AS default
            FROM pg_attribute f  
                JOIN pg_class c ON c.oid = f.attrelid  
                JOIN pg_type t ON t.oid = f.atttypid  
                LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum  
                LEFT JOIN pg_namespace n ON n.oid = c.relnamespace  
                LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)  
                LEFT JOIN pg_class AS g ON p.confrelid = g.oid  
            WHERE c.relkind = 'r'::char  
                AND n.nspname = '$schema' 
                AND c.relname = '$tableName'
                AND f.attnum > 0 ORDER BY number
        SQL;

        return $sql;
    }
}


================================================
FILE: pg4wp/rewriters/DropTableSQLRewriter.php
================================================
<?php

class DropTableSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        $sql = $this->original();

        $pattern = '/DROP TABLE.+ [`]?(\w+)[`]?$/';
        preg_match($pattern, $sql, $matches);
        $table = $matches[1];
        $seq = $table . '_seq';
        $sql .= ";\nDROP SEQUENCE IF EXISTS $seq;";

        return $sql;
    }
}


================================================
FILE: pg4wp/rewriters/InsertSQLRewriter.php
================================================
<?php

class InsertSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        global $wpdb;

        $sql = $this->original();

        // Those are used when we need to set the date to now() in gmt time
        $sql = str_replace("'0000-00-00 00:00:00'", 'now() AT TIME ZONE \'gmt\'', $sql);

        $sql = str_replace("utc_timestamp()", "CURRENT_TIMESTAMP AT TIME ZONE 'UTC'", $sql);

        // Multiple values group when calling INSERT INTO don't always work
        if(false !== strpos($sql, $wpdb->options) && false !== strpos($sql, '), (')) {
            $pattern = '/INSERT INTO.+VALUES/';
            preg_match($pattern, $sql, $matches);
            $insert = $matches[0];
            $sql = str_replace('), (', ');' . $insert . '(', $sql);
        }

        // Swap ON DUPLICATE KEY SYNTAX
        if(false !== $pos = strpos($sql, 'ON DUPLICATE KEY UPDATE')) {
            $splitStatements = function (string $sql): array {
                $statements = [];
                $buffer = '';
                $quote = null;

                for ($i = 0, $len = strlen($sql); $i < $len; $i++) {
                    $char = $sql[$i];

                    if ($quote) {
                        if ($char === $quote && $sql[$i - 1] !== '\\') {
                            $quote = null;
                        }
                    } elseif ($char === '"' || $char === "'") {
                        $quote = $char;
                    } elseif ($char === ';') {
                        $statements[] = $buffer . ';';
                        $buffer = '';
                        continue;
                    }

                    $buffer .= $char;
                }

                if (!empty($buffer)) {
                    $statements[] = $buffer;
                }

                return $statements;
            };

            $statements = $splitStatements($sql);

            foreach ($statements as $statement) {
                $statement = trim($statement);

                // Skip empty statements
                if (empty($statement)) {
                    continue;
                }

                // Replace backticks with double quotes for PostgreSQL compatibility
                $statement = str_replace('`', '"', $statement);

                // Find index positions for the SQL components
                $insertIndex = strpos($statement, 'INSERT INTO');
                $valuesIndex = strpos($statement, 'VALUES');
                $onDuplicateKeyIndex = strpos($statement, 'ON DUPLICATE KEY UPDATE');

                // Extract SQL components
                $tableSection = trim(substr($statement, $insertIndex, $valuesIndex - $insertIndex));
                $valuesSection = trim(substr($statement, $valuesIndex, $onDuplicateKeyIndex - $valuesIndex));
                $updateSection = trim(str_replace('ON DUPLICATE KEY UPDATE', '', substr($statement, $onDuplicateKeyIndex)));

                // Extract and clean up column names from the update section
                $updateCols = explode(',', $updateSection);
                $updateCols = array_map(function ($col) {
                    return trim(explode('=', $col)[0]);
                }, $updateCols);

                // Choose a primary key for ON CONFLICT
                $primaryKey = 'option_name';
                if (!in_array($primaryKey, $updateCols)) {
                    $primaryKey = 'meta_name';
                    if (!in_array($primaryKey, $updateCols)) {
                        $primaryKey = $updateCols[0] ?? '';
                    }
                }

                // Construct the PostgreSQL ON CONFLICT DO UPDATE section
                $updateSection = implode(', ', array_map(fn ($col) => "$col = EXCLUDED.$col", $updateCols));

                // Construct the PostgreSQL query
                $postgresSQL = sprintf('%s %s ON CONFLICT (%s) DO UPDATE SET %s', $tableSection, $valuesSection, $primaryKey, $updateSection);

                // Append to the converted statements list
                $convertedStatements[] = $postgresSQL;
            }

            $sql = implode('; ', $convertedStatements);
        } elseif(0 === strpos($sql, 'INSERT IGNORE')) {
            // Note: Requires PostgreSQL 9.5
            $sql = 'INSERT' . substr($sql, 13) . ' ON CONFLICT DO NOTHING';
        }

        // To avoid Encoding errors when inserting data coming from outside
        if(preg_match('/^.{1}/us', $sql, $ar) != 1) {
            $sql = utf8_encode($sql);
        }

        if(false === strpos($sql, 'RETURNING')) {
            $end_of_statement = $this->findSemicolon($sql);
            if ($end_of_statement !== false) {
                // Create the substrings up to and after the semicolon
                $sql_before_semicolon = substr($sql, 0, $end_of_statement);
                $sql_after_semicolon = substr($sql, $end_of_statement, strlen($sql));

                // Splice the SQL string together with 'RETURNING *'
                $sql = $sql_before_semicolon . ' RETURNING *' . $sql_after_semicolon;

            } else {
                $sql = $sql .= " RETURNING *";
            }
        }

        return $sql;
    }

    // finds semicolons that aren't in variables
    private function findSemicolon($sql)
    {
        $quoteOpened = false;
        $parenthesisDepth = 0;

        $sqlAsArray = str_split($sql);
        for($i = 0; $i < count($sqlAsArray); $i++) {
            if(($sqlAsArray[$i] == '"' || $sqlAsArray[$i] == "'") && ($i == 0 || $sqlAsArray[$i - 1] != '\\')) {
                $quoteOpened = !$quoteOpened;
            } elseif($sqlAsArray[$i] == '(' && !$quoteOpened) {
                $parenthesisDepth++;
            } elseif($sqlAsArray[$i] == ')' && !$quoteOpened) {
                $parenthesisDepth--;
            } elseif($sqlAsArray[$i] == ';' && !$quoteOpened && $parenthesisDepth == 0) {
                return $i;
            }
        }
        return false;
    }
}


================================================
FILE: pg4wp/rewriters/OptimizeTableSQLRewriter.php
================================================
<?php

class OptimizeTableSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        $sql = $this->original();
        return str_replace('OPTIMIZE TABLE', 'VACUUM', $sql);
    }
}


================================================
FILE: pg4wp/rewriters/ReplaceIntoSQLRewriter.php
================================================
<?php

class ReplaceIntoSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        global $wpdb;

        $sql = $this->original();

        $splitStatements = function (string $sql): array {
            $statements = [];
            $buffer = '';
            $quote = null;

            for ($i = 0, $len = strlen($sql); $i < $len; $i++) {
                $char = $sql[$i];

                if ($quote) {
                    if ($char === $quote && $sql[$i - 1] !== '\\') {
                        $quote = null;
                    }
                } elseif ($char === '"' || $char === "'") {
                    $quote = $char;
                } elseif ($char === ';') {
                    $statements[] = $buffer . ';';
                    $buffer = '';
                    continue;
                }

                $buffer .= $char;
            }

            if (!empty($buffer)) {
                $statements[] = $buffer;
            }

            return $statements;
        };

        $statements = $splitStatements($sql);

        foreach ($statements as $statement) {
            $statement = trim($statement);

            // Skip empty statements
            if (empty($statement)) {
                continue;
            }

            // Replace backticks with double quotes for PostgreSQL compatibility
            $statement = str_replace('`', '"', $statement);

            // Find index positions for the SQL components
            $insertIndex = strpos($statement, 'REPLACE INTO');
            $columnsStartIndex = strpos($statement, "(");
            $columnsEndIndex = strpos($statement, ")");
            $valuesIndex = strpos($statement, 'VALUES');
            $onDuplicateKeyIndex = strpos($statement, 'ON DUPLICATE KEY UPDATE');

            // Extract SQL components
            $tableSection = trim(substr($statement, $insertIndex, $columnsStartIndex - $insertIndex));
            $valuesSection = trim(substr($statement, $valuesIndex, strlen($statement) - $valuesIndex));
            $columnsSection = trim(substr($statement, $columnsStartIndex, $columnsEndIndex - $columnsStartIndex + 1));

            // Extract and clean up column names from the update section
            $updateCols = explode(',', substr($columnsSection, 1, strlen($columnsSection) - 2));
            $updateCols = array_map(function ($col) {
                return  trim($col);
            }, $updateCols);

            // Choose a primary key for ON CONFLICT
            $primaryKey = 'option_name';
            if (!in_array($primaryKey, $updateCols)) {
                $primaryKey = 'meta_name';
                if (!in_array($primaryKey, $updateCols)) {
                    $primaryKey = $updateCols[0] ?? '';
                }
            }

            // SWAP REPLACE INTO for INSERT INTO
            $tableSection = str_replace("REPLACE INTO", "INSERT INTO", $tableSection);

            // Construct the PostgreSQL ON CONFLICT DO UPDATE section
            $updateSection = "";
            foreach($updateCols as $col) {
                if ($col !== $primaryKey) {
                    $updateSection .= ", ";
                    $updateSection .= "$col = EXCLUDED.$col";
                }
            }

            // trim any preceding commas
            $updateSection = ltrim($updateSection, ", ");

            // Construct the PostgreSQL query
            $postgresSQL = sprintf('%s %s %s ON CONFLICT (%s) DO UPDATE SET %s', $tableSection, $columnsSection, $valuesSection, $primaryKey, $updateSection);

            if(false === strpos($postgresSQL, 'RETURNING')) {
                $end_of_statement = $this->findSemicolon($postgresSQL);
                if ($end_of_statement !== false) {
                    // Create the substrings up to and after the semicolon
                    $sql_before_semicolon = substr($postgresSQL, 0, $end_of_statement);
                    $sql_after_semicolon = substr($postgresSQL, $end_of_statement, strlen($postgresSQL));
    
                    // Splice the SQL string together with 'RETURNING *'
                    $postgresSQL = $sql_before_semicolon . ' RETURNING *' . $sql_after_semicolon;
    
                } else {
                    $postgresSQL = $postgresSQL .= " RETURNING *";
                }
            }

            // Append to the converted statements list
            $convertedStatements[] = $postgresSQL;
        }

        $sql = implode('; ', $convertedStatements);

        return $sql;
    }

      // finds semicolons that aren't in variables
      private function findSemicolon($sql)
      {
          $quoteOpened = false;
          $parenthesisDepth = 0;
  
          $sqlAsArray = str_split($sql);
          for($i = 0; $i < count($sqlAsArray); $i++) {
              if(($sqlAsArray[$i] == '"' || $sqlAsArray[$i] == "'") && ($i == 0 || $sqlAsArray[$i - 1] != '\\')) {
                  $quoteOpened = !$quoteOpened;
              } elseif($sqlAsArray[$i] == '(' && !$quoteOpened) {
                  $parenthesisDepth++;
              } elseif($sqlAsArray[$i] == ')' && !$quoteOpened) {
                  $parenthesisDepth--;
              } elseif($sqlAsArray[$i] == ';' && !$quoteOpened && $parenthesisDepth == 0) {
                  return $i;
              }
          }
          return false;
      }
}


================================================
FILE: pg4wp/rewriters/SelectSQLRewriter.php
================================================
<?php

class SelectSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        global $wpdb;

        $sql = $this->original();

        // SQL_CALC_FOUND_ROWS doesn't exist in PostgreSQL but it's needed for correct paging
        if(false !== strpos($sql, 'SQL_CALC_FOUND_ROWS')) {
            $sql = str_replace('SQL_CALC_FOUND_ROWS', '', $sql);
            $GLOBALS['pg4wp_numrows_query'] = $sql;
            if(PG4WP_DEBUG) {
                error_log('[' . microtime(true) . "] Number of rows required for :\n$sql\n---------------------\n", 3, PG4WP_LOG . 'pg4wp_NUMROWS.log');
            }
        }

        if(false !== strpos($sql, 'FOUND_ROWS()')) {
            // Here we convert the latest query into a COUNT query
            $sql = $GLOBALS['pg4wp_numrows_query'];

            // Remove the LIMIT clause if it exists
            $sql = preg_replace('/\s+LIMIT\s+\d+(\s*,\s*\d+)?/i', '', $sql);

            // Remove the ORDER BY containing case / end clause if it exists
            $sql = preg_replace('/\s+ORDER\s+BY\s+.+END\),[^)]+/is', '', $sql);

            // Remove the ORDER BY clause if it exists
            $sql = preg_replace('/\s+ORDER\s+BY\s+[^)]+/i', '', $sql);

            // Replace the fields in the SELECT clause with COUNT(*)
            $sql = preg_replace('/SELECT\s+.*?\s+FROM\s+/is', 'SELECT COUNT(*) FROM ', $sql, 1);
        }

        if(false !== strpos($sql, 'information_schema')) {
            // WP Site Health rewrites
            if (false !== strpos($sql, "SELECT TABLE_NAME AS 'table', TABLE_ROWS AS 'rows', SUM(data_length + index_length)")) {
                $sql = $this->postgresTableSizeRewrite();
                return $sql;
            }

            throw new Exception("Unsupported call to information_schema, this probably won't work correctly and needs to be specifically handled, open a github issue with the SQL");
        }

        $sql = $this->ensureOrderByInSelect($sql);

        // Handle +0 casting in order by
        // Regular expression to match the "ORDER BY" pattern
        $pattern = '/ORDER BY\s+([a-zA-Z0-9_]+)\.meta_value\s*\+\s*0/i';
        $replacement = 'ORDER BY CAST($1.meta_value AS SIGNED)';
        $sql = preg_replace($pattern, $replacement, $sql);

        // Convert CONVERT to CAST
        $pattern = '/CONVERT\(([^()]*(\(((?>[^()]+)|(?-2))*\))?[^()]*),\s*([^\s]+)\)/x';
        $sql = preg_replace($pattern, 'CAST($1 AS $4)', $sql);

        // Handle CAST( ... AS CHAR)
        $sql = preg_replace('/CAST\((.+) AS CHAR\)/', 'CAST($1 AS TEXT)', $sql);

        // Handle CAST( ... AS SIGNED)
        $sql = preg_replace('/CAST\((.+) AS SIGNED\)/', 'CAST($1 AS INTEGER)', $sql);

        // Handle COUNT(*)...ORDER BY...
        $sql = preg_replace('/COUNT(.+)ORDER BY.+/s', 'COUNT$1', $sql);

        // HANDLE REGEXP
        $sql = preg_replace('/REGEXP/', '~', $sql);

        $sql = str_replace("utc_timestamp()", "CURRENT_TIMESTAMP AT TIME ZONE 'UTC'", $sql);

        // In order for users counting to work...
        $matches = array();
        if(preg_match_all('/COUNT[^C]+\),/', $sql, $matches)) {
            foreach($matches[0] as $num => $one) {
                $sub = substr($one, 0, -1);
                $sql = str_replace($sub, $sub . ' AS count' . $num, $sql);
            }
        }

        $sql = $this->convertToPostgresLimitSyntax($sql);
        $sql = $this->ensureGroupByOrAggregate($sql);

        $pattern = '/DATE_ADD[ ]*\(([^,]+),([^\)]+)\)/';
        $sql = preg_replace($pattern, '($1 + $2)', $sql);

        // Convert MySQL FIELD function to CASE statement
        $pattern = '/FIELD[ ]*\(([^\),]+),([^\)]+)\)/';
        // https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_field
        // Other implementations:  https://stackoverflow.com/q/1309624
        $sql = preg_replace_callback($pattern, function ($matches) {
            $case = 'CASE ' . trim($matches[1]);
            $comparands = explode(',', $matches[2]);
            foreach($comparands as $i => $comparand) {
                $case .= ' WHEN ' . trim($comparand) . ' THEN ' . ($i + 1);
            }
            $case .= ' ELSE 0 END';
            return $case;
        }, $sql);

        $pattern = '/GROUP_CONCAT\(([^()]*(\(((?>[^()]+)|(?-2))*\))?[^()]*)\)/x';
        $sql = preg_replace($pattern, "string_agg($1, ',')", $sql);

        // Convert MySQL RAND function to PostgreSQL RANDOM function
        $pattern = '/RAND[ ]*\([ ]*\)/';
        $sql = preg_replace($pattern, 'RANDOM()', $sql);

        // UNIX_TIMESTAMP in MYSQL returns an integer
        $pattern = '/UNIX_TIMESTAMP\(([^\)]+)\)/';
        $sql = preg_replace($pattern, 'ROUND(DATE_PART(\'epoch\',$1))', $sql);

        $date_funcs = array(
            'DAYOFMONTH('	=> 'EXTRACT(DAY FROM ',
            'YEAR('			=> 'EXTRACT(YEAR FROM ',
            'MONTH('		=> 'EXTRACT(MONTH FROM ',
            'DAY('			=> 'EXTRACT(DAY FROM ',
        );

        $sql = str_replace('ORDER BY post_date DESC', 'ORDER BY YEAR(post_date) DESC, MONTH(post_date) DESC', $sql);
        $sql = str_replace('ORDER BY post_date ASC', 'ORDER BY YEAR(post_date) ASC, MONTH(post_date) ASC', $sql);
        $sql = str_replace(array_keys($date_funcs), array_values($date_funcs), $sql);
        $curryear = date('Y');
        $sql = str_replace('FROM \'' . $curryear, 'FROM TIMESTAMP \'' . $curryear, $sql);

        // MySQL 'IF' conversion - Note : NULLIF doesn't need to be corrected
        $pattern = '/ (?<!NULL)IF[ ]*\(([^,]+),([^,]+),([^\)]+)\)/';
        $sql = preg_replace($pattern, ' CASE WHEN $1 THEN $2 ELSE $3 END', $sql);

        // Act like MySQL default configuration, where sql_mode is ""
        $pattern = '/@@SESSION.sql_mode/';
        $sql = preg_replace($pattern, "''", $sql);


        // TODO: this seems wrong but if we remove it we get failures with XYZ is not part of the group By
        if(isset($wpdb)) {
            $sql = str_replace('GROUP BY ' . $wpdb->prefix . 'posts.ID', '', $sql);
        }

        // MySQL 'LIKE' is case insensitive by default, whereas PostgreSQL 'LIKE' is
        $sql = str_replace(' LIKE ', ' ILIKE ', $sql);

        // INDEXES are not yet supported
        if(false !== strpos($sql, 'USE INDEX (comment_date_gmt)')) {
            $sql = str_replace('USE INDEX (comment_date_gmt)', '', $sql);
        }

        // HB : timestamp fix for permalinks
        $sql = str_replace('post_date_gmt > 1970', 'post_date_gmt > to_timestamp (\'1970\')', $sql);

        // Akismet sometimes doesn't write 'comment_ID' with 'ID' in capitals where needed ...
        if(isset($wpdb) && $wpdb->comments && false !== strpos($sql, $wpdb->comments)) {
            $sql = str_replace(' comment_id ', ' comment_ID ', $sql);
        }

        // MySQL treats a HAVING clause without GROUP BY like WHERE
        if(false !== strpos($sql, 'HAVING') && false === strpos($sql, 'GROUP BY')) {
            if(false === strpos($sql, 'WHERE')) {
                $sql = str_replace('HAVING', 'WHERE', $sql);
            } else {
                $pattern = '/WHERE\s+(.*?)\s+HAVING\s+(.*?)(\s*(?:ORDER|LIMIT|PROCEDURE|INTO|FOR|LOCK|$))/';
                $sql = preg_replace($pattern, 'WHERE ($1) AND ($2) $3', $sql);
            }
        }

        // MySQL allows integers to be used as boolean expressions
        // where 0 is false and all other values are true.
        //
        // Although this could occur anywhere with any number, so far it
        // has only been observed as top-level expressions in the WHERE
        // clause and only with 0.  For performance, limit current
        // replacements to that.
        $pattern_after_where = '(?:\s*$|\s+(GROUP|HAVING|ORDER|LIMIT|PROCEDURE|INTO|FOR|LOCK))';
        $pattern = '/(WHERE\s+)0(\s+AND|\s+OR|' . $pattern_after_where . ')/';
        $sql = preg_replace($pattern, '$1false$2', $sql);

        $pattern = '/(AND\s+|OR\s+)0(' . $pattern_after_where . ')/';
        $sql = preg_replace($pattern, '$1false$2', $sql);

        // MySQL supports strings as names, PostgreSQL needs identifiers.
        // Limit to after closing parenthesis to reduce false-positives
        // Currently only an issue for nextgen-gallery plugin
        $pattern = '/\) AS \'([^\']+)\'/';
        $sql = preg_replace($pattern, ') AS "$1"', $sql);

        return $sql;
    }

    /**
     * Ensure the columns used in the ORDER BY clause are also present in the SELECT clause.
     *
     * @param string $sql Original SQL query string.
     * @return string Modified SQL query string.
     */
    protected function ensureOrderByInSelect(string $sql): string
    {
        // Extract the SELECT and ORDER BY clauses
        preg_match('/SELECT\s+(.*?)\s+FROM/si', $sql, $selectMatches);
        preg_match('/ORDER BY(.*?)(ASC|DESC|$)/si', $sql, $orderMatches);
        preg_match('/GROUP BY(.*?)(ASC|DESC|$)/si', $sql, $groupMatches);

        // If the SELECT clause is missing, return the original query
        if (!$selectMatches) {
            return $sql;
        }

        // If both ORDER BY and GROUP BY clauses are missing, return the original query
        if (!$orderMatches && !$groupMatches) {
            return $sql;
        }

        $selectClause = trim($selectMatches[1]);
        $orderByClause = $orderMatches ? trim($orderMatches[1]) : null;
        $groupClause = $groupMatches ? trim($groupMatches[1]) : null;
        $modified = false;

        // Check for wildcard in SELECT
        if (strpos($selectClause, '*') !== false) {
            return $sql; // Cannot handle wildcards, return original query
        }

        // Handle ORDER BY columns
        if ($orderByClause) {
            $orderByColumns = explode(',', $orderByClause);
            foreach ($orderByColumns as $col) {
                $col = trim($col);
                if (strpos($selectClause, $col) === false) {
                    $selectClause .= ', ' . $col;
                    $modified = true;
                }
            }
        }

        // Handle GROUP BY columns
        if ($groupClause && !$modified) {
            $groupColumns = explode(',', $groupClause);
            foreach ($groupColumns as $col) {
                $col = trim($col);
                if (strpos($selectClause, $col) === false) {
                    $selectClause .= ', ' . $col;
                    $modified = true;
                }
            }
        }

        if (!$modified) {
            return $sql;
        }

        // Find the exact position for the replacement
        $selectStartPos = strpos($sql, $selectMatches[1]);
        if ($selectStartPos === false) {
            return $sql; // If for some reason the exact match is not found, return the original query
        }
        $postgresSql = substr_replace($sql, $selectClause, $selectStartPos, strlen($selectMatches[1]));

        return $postgresSql;
    }

    /**
     * Transforms a given SQL query to include a GROUP BY clause if the SELECT statement has both aggregate
     * and non-aggregate columns. This function is specifically designed to work with PostgreSQL.
     *
     * In PostgreSQL, a query that uses aggregate functions must group by all columns in the SELECT list that
     * are not part of the aggregate functions. Failing to do so results in a syntax error. This function
     * automatically adds a GROUP BY clause to meet this PostgreSQL requirement when both aggregate (COUNT, SUM,
     * AVG, MIN, MAX) and non-aggregate columns are present.
     *
     * @param string $sql The SQL query string to be transformed.
     *
     * @return string The transformed SQL query string with appropriate GROUP BY clause if required.
     *
     * @throws Exception If the SQL query cannot be parsed or modified.
     *
     * @example
     * Input:  SELECT COUNT(id), username FROM users;
     * Output: SELECT COUNT(id), username FROM users GROUP BY username;
     *
     */
    protected function ensureGroupByOrAggregate(string $sql): string
    {
        // Check for system or session variables
        if (preg_match('/@@[a-zA-Z0-9_]+/', $sql)) {
            return $sql;
        }

        // Regular expression to capture main SQL components.
        $regex = '/(SELECT\s+)(.*?)(\s+FROM\s+)([^ ]+)(\s+WHERE\s+.*?(?= ORDER BY | GROUP BY | LIMIT |$))?(ORDER BY.*?(?= LIMIT |$))?(LIMIT.*?$)?/is';

        // Capture main SQL components using regex
        if (!preg_match($regex, $sql, $matches)) {
            return $sql;
        }

        $selectClause = trim($matches[2] ?? '');
        $fromClause = trim($matches[4] ?? '');
        $whereClause = trim($matches[5] ?? '');
        $orderClause = trim($matches[6] ?? '');
        $limitClause = trim($matches[7] ?? '');

        if (empty($selectClause) || empty($fromClause)) {
            return $sql;
        }

        // Regular expression to match commas not within parentheses
        $pattern = '/,(?![^\(]*\))/';
        // Split columns using a comma, and then trim each element
        $columns = array_map('trim', preg_split($pattern, $selectClause));

        $aggregateColumns = [];
        $nonAggregateColumns = [];

        foreach ($columns as $col) {
            // Check for aggregate functions in the column
            if (preg_match('/(COUNT|SUM|AVG|MIN|MAX)\s*?\(/i', $col)) {
                $aggregateColumns[] = $col;
            } else {
                $nonAggregateColumns[] = $col;
            }
        }

        // Only add a GROUP BY clause if there are both aggregate and non-aggregate columns in SELECT
        if (empty($aggregateColumns) || empty($nonAggregateColumns)) {
            return $sql;
        }


        // Assemble new SQL query
        $postgresSql = "SELECT $selectClause FROM $fromClause";

        if (!empty($whereClause)) {
            $postgresSql .= ' ' . $whereClause;
        }

        $groupByClause = "GROUP BY " . implode(", ", $nonAggregateColumns);
        if (!empty($groupByClause)) {
            $postgresSql .= ' ' . $groupByClause;
        }

        if (!empty($orderClause)) {
            $postgresSql .= ' ' . $orderClause;
        }

        if (!empty($limitClause)) {
            $postgresSql .= ' ' . $limitClause;
        }

        return $postgresSql;
    }

    /**
     * Convert MySQL LIMIT syntax to PostgreSQL LIMIT syntax
     *
     * @param string $sql MySQL query string
     * @return string PostgreSQL query string
     */
    protected function convertToPostgresLimitSyntax($sql)
    {
        // Use regex to find "LIMIT m, n" syntax in query
        if (preg_match('/LIMIT\s+(\d+),\s*(\d+)/i', $sql, $matches)) {
            $offset = $matches[1];
            $limit = $matches[2];

            // Replace MySQL LIMIT syntax with PostgreSQL LIMIT syntax
            $postgresLimitSyntax = "LIMIT $limit OFFSET $offset";
            $postgresSql = preg_replace('/LIMIT\s+\d+,\s*\d+/i', $postgresLimitSyntax, $sql);

            return $postgresSql;
        }

        // Return original query if no MySQL LIMIT syntax is found
        return $sql;
    }

    // This method is specifically to handle should_suggest_persistent_object_cache in wp site health
    protected function postgresTableSizeRewrite($schema = 'public')
    {

        $sql = <<<SQL
        SELECT 
            C.relname AS "table", 
            S.n_live_tup AS "rows", 
            pg_total_relation_size(C.oid) AS "bytes"
        FROM 
            pg_class C 
        LEFT JOIN 
            pg_namespace N ON (N.oid = C.relnamespace) 
        INNER JOIN 
            pg_stat_user_tables S ON (S.relid = C.oid) 
        WHERE 
            N.nspname = '$schema' AND 
            C.relname IN ('wp_comments','wp_options','wp_posts','wp_terms','wp_users')
        GROUP BY 
            C.relname, pg_total_relation_size(C.oid), S.n_live_tup;
        SQL;

        return $sql;
    }

}


================================================
FILE: pg4wp/rewriters/SetNamesSQLRewriter.php
================================================
<?php

class SetNamesSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        return "SET NAMES 'utf8'";
    }
}


================================================
FILE: pg4wp/rewriters/ShowFullColumnsSQLRewriter.php
================================================
<?php

class ShowFullColumnsSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        $sql = $this->original();
        $table = $this->extractTableNameFromShowColumns($sql);
        return $this->generatePostgresShowColumns($table);
    }

    /**
     * Extracts table name from a "SHOW FULL COLUMNS" SQL statement.
     *
     * @param string $sql The SQL statement
     * @return string|null The table name if found, or null otherwise
     */
    protected function extractTableNameFromShowColumns($sql)
    {
        $pattern = "/SHOW FULL COLUMNS FROM ['\"`]?([^'\"`]+)['\"`]?/i";
        if (preg_match($pattern, $sql, $matches)) {
            return $matches[1];
        }
        return null;
    }

    /**
     * Generates a PostgreSQL-compatible SQL query to mimic MySQL's "SHOW FULL COLUMNS".
     *
     * @param string $tableName The table name
     * @param string $schema The schema name
     * @return string The generated SQL query
     */
    public function generatePostgresShowColumns($tableName, $schema = "public")
    {
        $sql = <<<SQL
            SELECT 
                a.attname AS "Field",
                pg_catalog.format_type(a.atttypid, a.atttypmod) AS "Type",
                (CASE 
                    WHEN a.attnotnull THEN 'NO' 
                    ELSE 'YES' 
                END) AS "Null",
                (CASE 
                    WHEN i.indisprimary THEN 'PRI'
                    WHEN i.indisunique THEN 'UNI'
                    ELSE '' 
                END) AS "Key",
                pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) AS "Default",
                '' AS "Extra",
                'select,insert,update,references' AS "Privileges",
                d.description AS "Comment"
            FROM 
                pg_catalog.pg_attribute a
                LEFT JOIN pg_catalog.pg_description d ON (a.attrelid = d.objoid AND a.attnum = d.objsubid)
                LEFT JOIN pg_catalog.pg_attrdef ad ON (a.attrelid = ad.adrelid AND a.attnum = ad.adnum)
                LEFT JOIN pg_catalog.pg_index i ON (a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey))
            WHERE 
                a.attnum > 0 
                AND NOT a.attisdropped
                AND a.attrelid = (
                    SELECT c.oid
                    FROM pg_catalog.pg_class c
                    LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
                    WHERE c.relname = '$tableName'
                    AND n.nspname = '$schema'
                )
            ORDER BY 
                a.attnum;
        SQL;

        return $sql;
    }
}


================================================
FILE: pg4wp/rewriters/ShowIndexSQLRewriter.php
================================================
<?php

class ShowIndexSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        $sql = $this->original();
        $table = $this->extractTableNameFromShowIndex($sql);
        return $this->generatePostgresShowIndexFrom($table);
    }

    /**
     * Extracts table name from a "SHOW FULL COLUMNS" SQL statement.
     *
     * @param string $sql The SQL statement
     * @return string|null The table name if found, or null otherwise
     */
    protected function extractVariableName($sql)
    {
        $pattern = "/SHOW INDEX FROM ['\"`]?([^'\"`]+)['\"`]?/i";
        if (preg_match($pattern, $sql, $matches)) {
            return $matches[1];
        }
        return null;
    }

    /**
     * Generates a PostgreSQL-compatible SQL query to mimic MySQL's "SHOW INDEX FROM".
     *
     * @param string $tableName The table name
     * @return string The generated SQL query
     */
    public function generatePostgresShowIndexFrom($tableName)
    {
        $sql = <<<SQL
        SELECT bc.relname AS "Table",
            CASE WHEN i.indisunique THEN '0' ELSE '1' END AS "Non_unique",
            CASE WHEN i.indisprimary THEN 'PRIMARY' WHEN bc.relname LIKE '%usermeta' AND ic.relname = 'umeta_key'
                THEN 'meta_key' ELSE REPLACE( ic.relname, '' . $table . '_', '') END AS "Key_name",
            a.attname AS "Column_name",
            NULL AS "Sub_part"
        FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a
        WHERE bc.oid = i.indrelid
            AND ic.oid = i.indexrelid
            AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum)
            AND a.attrelid = bc.oid
            AND bc.relname = '' . $tableName . ''
            ORDER BY "Key_name", CASE a.attnum
                WHEN i.indkey[0] THEN 0
                WHEN i.indkey[1] THEN 1
                WHEN i.indkey[2] THEN 2
                WHEN i.indkey[3] THEN 3
                WHEN i.indkey[4] THEN 4
                WHEN i.indkey[5] THEN 5
                WHEN i.indkey[6] THEN 6
                WHEN i.indkey[7] THEN 7
            END
        SQL;

        return $sql;
    }
}


================================================
FILE: pg4wp/rewriters/ShowTableStatusSQLRewriter.php
================================================
<?php

class ShowTableStatusSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        $sql = $this->original();
        return $this->generatePostgresShowTableStatus();
    }


    /**
     * Generates a PostgreSQL-compatible SQL query to mimic MySQL's "SHOW TABLE STATUS".
     *
     * @return string The generated SQL query
     */
    public function generatePostgresShowTableStatus($schema = "public")
    {
        $sql = <<<SQL
        SELECT 
            'Postgres' AS Engine,
            cls.relname AS TableName, 
            NULL AS Version,
            NULL AS Row_format,
            cls.reltuples AS Rows,
            NULL AS Avg_row_length,
            pg_size_pretty(pg_relation_size(cls.oid)) AS Data_length,
            NULL AS Max_data_length,
            pg_size_pretty(pg_indexes_size(cls.oid)) AS Index_length, 
            NULL AS Data_free,
            NULL AS Auto_increment,
            NULL AS Create_time,
            NULL AS Update_time,
            NULL AS Check_time,
            'UTF8' AS Table_collation,
            NULL AS Checksum,
            NULL AS Create_options,
            obj_description(cls.oid) AS Comment
        FROM
            pg_class cls
        JOIN 
            pg_namespace nsp ON cls.relnamespace = nsp.oid
        WHERE 
            cls.relkind = 'r' 
            AND nsp.nspname NOT LIKE 'pg_%' 
            AND nsp.nspname != 'information_schema' 
            AND nsp.nspname = '$schema' 
        ORDER BY 
            cls.relname ASC;
        SQL;

        return $sql;
    }
}


================================================
FILE: pg4wp/rewriters/ShowTablesSQLRewriter.php
================================================
<?php

class ShowTablesSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        $schema = "public";
        return 'SELECT tablename FROM pg_tables WHERE schemaname = \'$schema\';';
    }
}


================================================
FILE: pg4wp/rewriters/ShowVariablesSQLRewriter.php
================================================
<?php

class ShowVariablesSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        $sql = $this->original();
        $variableName = $this->extractVariableName($sql);
        return $this->generatePostgres($sql, $variableName);
    }

    /**
     * Extracts Variable name from a "SHOW VARIABLES LIKE " SQL statement.
     *
     * @param string $sql The SQL statement
     * @return string|null The table name if found, or null otherwise
     */
    protected function extractVariableName($sql)
    {
        $pattern = "/SHOW VARIABLES LIKE ['\"`]?([^'\"`]+)['\"`]?/i";
        if (preg_match($pattern, $sql, $matches)) {
            return $matches[1];
        }
        return null;
    }

    /**
     * Generates a PostgreSQL-compatible SQL query to mimic MySQL's "SHOW VARIABLES".
     *
     * @param string $tableName The table name
     * @return string The generated SQL query
     */
    public function generatePostgres($sql, $variableName)
    {
        if ($variableName == "sql_mode") {
            // Act like MySQL default configuration, where sql_mode is ""
            return "SELECT '$variableName' AS \"Variable_name\", '' AS \"Value\";";
        }

        if ($variableName == "max_allowed_packet") {
            // Act like 1GB packet size, in practice this limit doesn't actually exist for postgres, we just want to fool WP
            return "SELECT '$variableName' AS \"Variable_name\", '1073741824' AS \"Value\";";
        }

        return "SELECT name as \"Variable_name\", setting as \"Value\" FROM pg_settings WHERE name = '$variableName';";
    }
}


================================================
FILE: pg4wp/rewriters/UpdateSQLRewriter.php
================================================
<?php

class UpdateSQLRewriter extends AbstractSQLRewriter
{
    public function rewrite(): string
    {
        global $wpdb;

        $sql = $this->original();

        $pattern = '/LIMIT[ ]+\d+/';
        $sql = preg_replace($pattern, '', $sql);

        // Fix update wp_options
        $pattern = "/UPDATE `wp_options` SET `option_value` = NULL WHERE `option_name` = '(.+)'/";
        $match = "UPDATE `wp_options` SET `option_value` = '' WHERE `option_name` = '$1'";
        $sql = preg_replace($pattern, $match, $sql);

        // For correct bactick removal
        $pattern = '/[ ]*`([^` ]+)`[ ]*=/';
        $sql = preg_replace($pattern, ' $1 =', $sql);

        // Those are used when we need to set the date to now() in gmt time
        $sql = str_replace("'0000-00-00 00:00:00'", 'now() AT TIME ZONE \'gmt\'', $sql);

        // For correct ID quoting
        $pattern = '/(,|\s)[ ]*([^ \']*ID[^ \']*)[ ]*=/';
        $sql = preg_replace($pattern, '$1 "$2" =', $sql);

        return $sql;
    }
}


================================================
FILE: phpunit.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  displayDetailsOnTestsThatTriggerDeprecations="true"
  displayDetailsOnTestsThatTriggerErrors="true"
  displayDetailsOnTestsThatTriggerNotices="true"
  displayDetailsOnTestsThatTriggerWarnings="true"
  colors="true">
    <testsuites>
        <testsuite name="tests">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

================================================
FILE: readme.md
================================================
## PostgreSQL for WordPress (PG4WP) 

### Description 

PostgreSQL for WordPress (PG4WP) gives you the possibility to install and use WordPress with a PostgreSQL database as a backend.

#### Use Cases

- Run Wordpress on your Existing Postgres Cluster
- Run Wordpress with Georeplication with a Multi-Active Postgres instalation such as [EDB Postgres Distributed](https://www.enterprisedb.com/products/edb-postgres-distributed), or [CockroachDB](https://www.cockroachlabs.com/serverless/) for a [highly available](https://www.cockroachlabs.com/blog/brief-h
Download .txt
gitextract_y00m6hv_/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── sql-rewriting-issue.md
│   ├── pull_request_template.md
│   └── workflows/
│       └── php.yml
├── .gitignore
├── license.md
├── pg4wp/
│   ├── core.php
│   ├── db.php
│   ├── driver_mysql.php
│   ├── driver_pgsql.php
│   ├── driver_pgsql_rewrite.php
│   └── rewriters/
│       ├── AbstractSQLRewriter.php
│       ├── AlterTableSQLRewriter.php
│       ├── CreateTableSQLRewriter.php
│       ├── DeleteSQLRewriter.php
│       ├── DescribeSQLRewriter.php
│       ├── DropTableSQLRewriter.php
│       ├── InsertSQLRewriter.php
│       ├── OptimizeTableSQLRewriter.php
│       ├── ReplaceIntoSQLRewriter.php
│       ├── SelectSQLRewriter.php
│       ├── SetNamesSQLRewriter.php
│       ├── ShowFullColumnsSQLRewriter.php
│       ├── ShowIndexSQLRewriter.php
│       ├── ShowTableStatusSQLRewriter.php
│       ├── ShowTablesSQLRewriter.php
│       ├── ShowVariablesSQLRewriter.php
│       └── UpdateSQLRewriter.php
├── phpunit.xml
├── readme.md
├── tests/
│   ├── parseTest.php
│   ├── rewriteTest.php
│   ├── stubs/
│   │   ├── delete-fro_1698679875.txt
│   │   ├── delete-fro_1698679877.txt
│   │   ├── delete-fro_1698679878.txt
│   │   ├── delete-fro_1698679918.txt
│   │   ├── delete-fro_1698679920.txt
│   │   ├── delete-fro_1698679954.txt
│   │   ├── delete-fro_1698679955.txt
│   │   ├── insert-int_1698679874.txt
│   │   ├── insert-int_1698679877.txt
│   │   ├── insert-int_1698679878.txt
│   │   ├── insert-int_1698679884.txt
│   │   ├── insert-int_1698679897.txt
│   │   ├── insert-int_1698679908.txt
│   │   ├── insert-int_1698679917.txt
│   │   ├── insert-int_1698679920.txt
│   │   ├── insert-int_1698679923.txt
│   │   ├── insert-int_1698679936.txt
│   │   ├── insert-int_1698679954.txt
│   │   ├── insert-int_1698679955.txt
│   │   ├── insert-int_1698679965.txt
│   │   ├── insert-int_1698679972.txt
│   │   ├── select-aut_1698679874.txt
│   │   ├── select-aut_1698679884.txt
│   │   ├── select-aut_1698679897.txt
│   │   ├── select-aut_1698679908.txt
│   │   ├── select-aut_1698679917.txt
│   │   ├── select-aut_1698679923.txt
│   │   ├── select-aut_1698679965.txt
│   │   ├── select-aut_1698679972.txt
│   │   ├── select-blo_1698679989.txt
│   │   ├── select-com_1698679872.txt
│   │   ├── select-com_1698679886.txt
│   │   ├── select-com_1698679936.txt
│   │   ├── select-cou_1698679872.txt
│   │   ├── select-cou_1698679874.txt
│   │   ├── select-cou_1698679884.txt
│   │   ├── select-cou_1698679886.txt
│   │   ├── select-cou_1698679889.txt
│   │   ├── select-cou_1698679900.txt
│   │   ├── select-cou_1698679910.txt
│   │   ├── select-cou_1698679917.txt
│   │   ├── select-cou_1698679926.txt
│   │   ├── select-cou_1698679929.txt
│   │   ├── select-cou_1698679931.txt
│   │   ├── select-cou_1698679936.txt
│   │   ├── select-cou_1698679941.txt
│   │   ├── select-cou_1698679949.txt
│   │   ├── select-cou_1698679952.txt
│   │   ├── select-cou_1698679955.txt
│   │   ├── select-cou_1698679965.txt
│   │   ├── select-cou_1698679972.txt
│   │   ├── select-cou_1698679984.txt
│   │   ├── select-dis_1698679872.txt
│   │   ├── select-dis_1698679874.txt
│   │   ├── select-dis_1698679876.txt
│   │   ├── select-dis_1698679884.txt
│   │   ├── select-dis_1698679885.txt
│   │   ├── select-dis_1698679886.txt
│   │   ├── select-dis_1698679910.txt
│   │   ├── select-dis_1698679917.txt
│   │   ├── select-dis_1698679929.txt
│   │   ├── select-dis_1698679931.txt
│   │   ├── select-dis_1698679936.txt
│   │   ├── select-dis_1698679941.txt
│   │   ├── select-dis_1698679949.txt
│   │   ├── select-dis_1698679952.txt
│   │   ├── select-dis_1698679955.txt
│   │   ├── select-dis_1698679965.txt
│   │   ├── select-dis_1698679972.txt
│   │   ├── select-dis_1698679984.txt
│   │   ├── select-fro_1698679872.txt
│   │   ├── select-fro_1698679873.txt
│   │   ├── select-fro_1698679874.txt
│   │   ├── select-fro_1698679875.txt
│   │   ├── select-fro_1698679876.txt
│   │   ├── select-fro_1698679883.txt
│   │   ├── select-fro_1698679884.txt
│   │   ├── select-fro_1698679886.txt
│   │   ├── select-fro_1698679887.txt
│   │   ├── select-fro_1698679889.txt
│   │   ├── select-fro_1698679897.txt
│   │   ├── select-fro_1698679900.txt
│   │   ├── select-fro_1698679907.txt
│   │   ├── select-fro_1698679910.txt
│   │   ├── select-fro_1698679911.txt
│   │   ├── select-fro_1698679917.txt
│   │   ├── select-fro_1698679918.txt
│   │   ├── select-fro_1698679919.txt
│   │   ├── select-fro_1698679922.txt
│   │   ├── select-fro_1698679923.txt
│   │   ├── select-fro_1698679924.txt
│   │   ├── select-fro_1698679926.txt
│   │   ├── select-fro_1698679929.txt
│   │   ├── select-fro_1698679931.txt
│   │   ├── select-fro_1698679935.txt
│   │   ├── select-fro_1698679936.txt
│   │   ├── select-fro_1698679940.txt
│   │   ├── select-fro_1698679941.txt
│   │   ├── select-fro_1698679949.txt
│   │   ├── select-fro_1698679950.txt
│   │   ├── select-fro_1698679952.txt
│   │   ├── select-fro_1698679954.txt
│   │   ├── select-fro_1698679955.txt
│   │   ├── select-fro_1698679956.txt
│   │   ├── select-fro_1698679960.txt
│   │   ├── select-fro_1698679965.txt
│   │   ├── select-fro_1698679972.txt
│   │   ├── select-fro_1698679984.txt
│   │   ├── select-fro_1698679985.txt
│   │   ├── select-fro_1698679987.txt
│   │   ├── select-fro_1698679988.txt
│   │   ├── select-fro_1698679989.txt
│   │   ├── select-fro_1698679991.txt
│   │   ├── select-fro_1698679992.txt
│   │   ├── select-fro_1698679996.txt
│   │   ├── select-fro_1698679999.txt
│   │   ├── select-fro_1698680063.txt
│   │   ├── select-fro_1698680183.txt
│   │   ├── select-fro_1698680305.txt
│   │   ├── select-id-_1698679924.txt
│   │   ├── select-id-_1698679926.txt
│   │   ├── select-met_1698679872.txt
│   │   ├── select-met_1698679874.txt
│   │   ├── select-met_1698679875.txt
│   │   ├── select-met_1698679876.txt
│   │   ├── select-met_1698679877.txt
│   │   ├── select-met_1698679878.txt
│   │   ├── select-met_1698679883.txt
│   │   ├── select-met_1698679884.txt
│   │   ├── select-met_1698679886.txt
│   │   ├── select-met_1698679887.txt
│   │   ├── select-met_1698679889.txt
│   │   ├── select-met_1698679897.txt
│   │   ├── select-met_1698679900.txt
│   │   ├── select-met_1698679907.txt
│   │   ├── select-met_1698679908.txt
│   │   ├── select-met_1698679910.txt
│   │   ├── select-met_1698679911.txt
│   │   ├── select-met_1698679917.txt
│   │   ├── select-met_1698679918.txt
│   │   ├── select-met_1698679919.txt
│   │   ├── select-met_1698679920.txt
│   │   ├── select-met_1698679922.txt
│   │   ├── select-met_1698679923.txt
│   │   ├── select-met_1698679924.txt
│   │   ├── select-met_1698679926.txt
│   │   ├── select-met_1698679929.txt
│   │   ├── select-met_1698679931.txt
│   │   ├── select-met_1698679935.txt
│   │   ├── select-met_1698679936.txt
│   │   ├── select-met_1698679940.txt
│   │   ├── select-met_1698679949.txt
│   │   ├── select-met_1698679950.txt
│   │   ├── select-met_1698679952.txt
│   │   ├── select-met_1698679954.txt
│   │   ├── select-met_1698679955.txt
│   │   ├── select-met_1698679956.txt
│   │   ├── select-met_1698679960.txt
│   │   ├── select-met_1698679965.txt
│   │   ├── select-met_1698679972.txt
│   │   ├── select-met_1698679984.txt
│   │   ├── select-met_1698679985.txt
│   │   ├── select-met_1698679987.txt
│   │   ├── select-met_1698679988.txt
│   │   ├── select-met_1698679989.txt
│   │   ├── select-met_1698679991.txt
│   │   ├── select-met_1698679992.txt
│   │   ├── select-met_1698679993.txt
│   │   ├── select-met_1698679996.txt
│   │   ├── select-met_1698679999.txt
│   │   ├── select-met_1698680063.txt
│   │   ├── select-met_1698680183.txt
│   │   ├── select-met_1698680305.txt
│   │   ├── select-opt_1698679872.txt
│   │   ├── select-opt_1698679874.txt
│   │   ├── select-opt_1698679875.txt
│   │   ├── select-opt_1698679876.txt
│   │   ├── select-opt_1698679883.txt
│   │   ├── select-opt_1698679884.txt
│   │   ├── select-opt_1698679886.txt
│   │   ├── select-opt_1698679887.txt
│   │   ├── select-opt_1698679889.txt
│   │   ├── select-opt_1698679897.txt
│   │   ├── select-opt_1698679900.txt
│   │   ├── select-opt_1698679907.txt
│   │   ├── select-opt_1698679908.txt
│   │   ├── select-opt_1698679910.txt
│   │   ├── select-opt_1698679911.txt
│   │   ├── select-opt_1698679917.txt
│   │   ├── select-opt_1698679918.txt
│   │   ├── select-opt_1698679919.txt
│   │   ├── select-opt_1698679922.txt
│   │   ├── select-opt_1698679923.txt
│   │   ├── select-opt_1698679924.txt
│   │   ├── select-opt_1698679926.txt
│   │   ├── select-opt_1698679929.txt
│   │   ├── select-opt_1698679931.txt
│   │   ├── select-opt_1698679935.txt
│   │   ├── select-opt_1698679936.txt
│   │   ├── select-opt_1698679940.txt
│   │   ├── select-opt_1698679941.txt
│   │   ├── select-opt_1698679949.txt
│   │   ├── select-opt_1698679950.txt
│   │   ├── select-opt_1698679952.txt
│   │   ├── select-opt_1698679954.txt
│   │   ├── select-opt_1698679955.txt
│   │   ├── select-opt_1698679956.txt
│   │   ├── select-opt_1698679960.txt
│   │   ├── select-opt_1698679965.txt
│   │   ├── select-opt_1698679972.txt
│   │   ├── select-opt_1698679984.txt
│   │   ├── select-opt_1698679985.txt
│   │   ├── select-opt_1698679987.txt
│   │   ├── select-opt_1698679988.txt
│   │   ├── select-opt_1698679989.txt
│   │   ├── select-opt_1698679991.txt
│   │   ├── select-opt_1698679992.txt
│   │   ├── select-opt_1698679993.txt
│   │   ├── select-opt_1698679996.txt
│   │   ├── select-opt_1698679999.txt
│   │   ├── select-opt_1698680063.txt
│   │   ├── select-opt_1698680183.txt
│   │   ├── select-opt_1698680305.txt
│   │   ├── select-pos_1698679872.txt
│   │   ├── select-pos_1698679873.txt
│   │   ├── select-pos_1698679874.txt
│   │   ├── select-pos_1698679876.txt
│   │   ├── select-pos_1698679884.txt
│   │   ├── select-pos_1698679885.txt
│   │   ├── select-pos_1698679886.txt
│   │   ├── select-pos_1698679887.txt
│   │   ├── select-pos_1698679910.txt
│   │   ├── select-pos_1698679911.txt
│   │   ├── select-pos_1698679917.txt
│   │   ├── select-pos_1698679919.txt
│   │   ├── select-pos_1698679923.txt
│   │   ├── select-pos_1698679924.txt
│   │   ├── select-pos_1698679926.txt
│   │   ├── select-pos_1698679929.txt
│   │   ├── select-pos_1698679931.txt
│   │   ├── select-pos_1698679936.txt
│   │   ├── select-pos_1698679941.txt
│   │   ├── select-pos_1698679949.txt
│   │   ├── select-pos_1698679952.txt
│   │   ├── select-pos_1698679955.txt
│   │   ├── select-pos_1698679956.txt
│   │   ├── select-pos_1698679965.txt
│   │   ├── select-pos_1698679972.txt
│   │   ├── select-pos_1698679984.txt
│   │   ├── select-ses_1698679872.txt
│   │   ├── select-ses_1698679874.txt
│   │   ├── select-ses_1698679875.txt
│   │   ├── select-ses_1698679876.txt
│   │   ├── select-ses_1698679883.txt
│   │   ├── select-ses_1698679884.txt
│   │   ├── select-ses_1698679886.txt
│   │   ├── select-ses_1698679887.txt
│   │   ├── select-ses_1698679889.txt
│   │   ├── select-ses_1698679897.txt
│   │   ├── select-ses_1698679900.txt
│   │   ├── select-ses_1698679907.txt
│   │   ├── select-ses_1698679910.txt
│   │   ├── select-ses_1698679911.txt
│   │   ├── select-ses_1698679917.txt
│   │   ├── select-ses_1698679918.txt
│   │   ├── select-ses_1698679919.txt
│   │   ├── select-ses_1698679922.txt
│   │   ├── select-ses_1698679923.txt
│   │   ├── select-ses_1698679924.txt
│   │   ├── select-ses_1698679926.txt
│   │   ├── select-ses_1698679928.txt
│   │   ├── select-ses_1698679931.txt
│   │   ├── select-ses_1698679935.txt
│   │   ├── select-ses_1698679936.txt
│   │   ├── select-ses_1698679940.txt
│   │   ├── select-ses_1698679949.txt
│   │   ├── select-ses_1698679950.txt
│   │   ├── select-ses_1698679952.txt
│   │   ├── select-ses_1698679953.txt
│   │   ├── select-ses_1698679954.txt
│   │   ├── select-ses_1698679955.txt
│   │   ├── select-ses_1698679956.txt
│   │   ├── select-ses_1698679960.txt
│   │   ├── select-ses_1698679965.txt
│   │   ├── select-ses_1698679972.txt
│   │   ├── select-ses_1698679984.txt
│   │   ├── select-ses_1698679985.txt
│   │   ├── select-ses_1698679987.txt
│   │   ├── select-ses_1698679988.txt
│   │   ├── select-ses_1698679989.txt
│   │   ├── select-ses_1698679991.txt
│   │   ├── select-ses_1698679992.txt
│   │   ├── select-ses_1698679995.txt
│   │   ├── select-ses_1698679999.txt
│   │   ├── select-ses_1698680063.txt
│   │   ├── select-ses_1698680183.txt
│   │   ├── select-ses_1698680304.txt
│   │   ├── select-sql_1698679872.txt
│   │   ├── select-sql_1698679874.txt
│   │   ├── select-sql_1698679875.txt
│   │   ├── select-sql_1698679876.txt
│   │   ├── select-sql_1698679884.txt
│   │   ├── select-sql_1698679886.txt
│   │   ├── select-sql_1698679917.txt
│   │   ├── select-sql_1698679918.txt
│   │   ├── select-sql_1698679919.txt
│   │   ├── select-sql_1698679923.txt
│   │   ├── select-sql_1698679929.txt
│   │   ├── select-sql_1698679931.txt
│   │   ├── select-sql_1698679936.txt
│   │   ├── select-sql_1698679941.txt
│   │   ├── select-sql_1698679952.txt
│   │   ├── select-sql_1698679954.txt
│   │   ├── select-sql_1698679955.txt
│   │   ├── select-sql_1698679956.txt
│   │   ├── select-sql_1698679989.txt
│   │   ├── select-sql_1698679991.txt
│   │   ├── select-t-t_1698679872.txt
│   │   ├── select-t-t_1698679874.txt
│   │   ├── select-t-t_1698679875.txt
│   │   ├── select-t-t_1698679876.txt
│   │   ├── select-t-t_1698679883.txt
│   │   ├── select-t-t_1698679884.txt
│   │   ├── select-t-t_1698679886.txt
│   │   ├── select-t-t_1698679887.txt
│   │   ├── select-t-t_1698679889.txt
│   │   ├── select-t-t_1698679897.txt
│   │   ├── select-t-t_1698679900.txt
│   │   ├── select-t-t_1698679907.txt
│   │   ├── select-t-t_1698679908.txt
│   │   ├── select-t-t_1698679910.txt
│   │   ├── select-t-t_1698679911.txt
│   │   ├── select-t-t_1698679917.txt
│   │   ├── select-t-t_1698679918.txt
│   │   ├── select-t-t_1698679919.txt
│   │   ├── select-t-t_1698679922.txt
│   │   ├── select-t-t_1698679923.txt
│   │   ├── select-t-t_1698679924.txt
│   │   ├── select-t-t_1698679926.txt
│   │   ├── select-t-t_1698679929.txt
│   │   ├── select-t-t_1698679931.txt
│   │   ├── select-t-t_1698679936.txt
│   │   ├── select-t-t_1698679941.txt
│   │   ├── select-t-t_1698679949.txt
│   │   ├── select-t-t_1698679950.txt
│   │   ├── select-t-t_1698679952.txt
│   │   ├── select-t-t_1698679954.txt
│   │   ├── select-t-t_1698679955.txt
│   │   ├── select-t-t_1698679956.txt
│   │   ├── select-t-t_1698679960.txt
│   │   ├── select-t-t_1698679965.txt
│   │   ├── select-t-t_1698679972.txt
│   │   ├── select-t-t_1698679984.txt
│   │   ├── select-t-t_1698679985.txt
│   │   ├── select-t-t_1698679987.txt
│   │   ├── select-t-t_1698679988.txt
│   │   ├── select-t-t_1698679989.txt
│   │   ├── select-t-t_1698679991.txt
│   │   ├── select-t-t_1698679992.txt
│   │   ├── select-t-t_1698679996.txt
│   │   ├── select-t-t_1698679999.txt
│   │   ├── select-t-t_1698680063.txt
│   │   ├── select-t-t_1698680183.txt
│   │   ├── select-t-t_1698680305.txt
│   │   ├── select-ter_1698679965.txt
│   │   ├── select-ter_1698679972.txt
│   │   ├── select-tt-_1698679897.txt
│   │   ├── select-tt-_1698679908.txt
│   │   ├── select-use_1698679872.txt
│   │   ├── select-use_1698679874.txt
│   │   ├── select-use_1698679875.txt
│   │   ├── select-use_1698679876.txt
│   │   ├── select-use_1698679883.txt
│   │   ├── select-use_1698679884.txt
│   │   ├── select-use_1698679886.txt
│   │   ├── select-use_1698679887.txt
│   │   ├── select-use_1698679889.txt
│   │   ├── select-use_1698679897.txt
│   │   ├── select-use_1698679900.txt
│   │   ├── select-use_1698679907.txt
│   │   ├── select-use_1698679910.txt
│   │   ├── select-use_1698679911.txt
│   │   ├── select-use_1698679917.txt
│   │   ├── select-use_1698679918.txt
│   │   ├── select-use_1698679919.txt
│   │   ├── select-use_1698679922.txt
│   │   ├── select-use_1698679923.txt
│   │   ├── select-use_1698679924.txt
│   │   ├── select-use_1698679926.txt
│   │   ├── select-use_1698679929.txt
│   │   ├── select-use_1698679931.txt
│   │   ├── select-use_1698679936.txt
│   │   ├── select-use_1698679941.txt
│   │   ├── select-use_1698679949.txt
│   │   ├── select-use_1698679950.txt
│   │   ├── select-use_1698679952.txt
│   │   ├── select-use_1698679954.txt
│   │   ├── select-use_1698679955.txt
│   │   ├── select-use_1698679956.txt
│   │   ├── select-use_1698679960.txt
│   │   ├── select-use_1698679965.txt
│   │   ├── select-use_1698679972.txt
│   │   ├── select-use_1698679984.txt
│   │   ├── select-use_1698679985.txt
│   │   ├── select-use_1698679987.txt
│   │   ├── select-use_1698679988.txt
│   │   ├── select-use_1698679989.txt
│   │   ├── select-use_1698679991.txt
│   │   ├── select-use_1698679992.txt
│   │   ├── select-use_1698679996.txt
│   │   ├── select-use_1698679999.txt
│   │   ├── select-use_1698680063.txt
│   │   ├── select-use_1698680183.txt
│   │   ├── select-use_1698680305.txt
│   │   ├── select-wp-_1698679872.txt
│   │   ├── select-wp-_1698679875.txt
│   │   ├── select-wp-_1698679883.txt
│   │   ├── select-wp-_1698679884.txt
│   │   ├── select-wp-_1698679887.txt
│   │   ├── select-wp-_1698679889.txt
│   │   ├── select-wp-_1698679897.txt
│   │   ├── select-wp-_1698679900.txt
│   │   ├── select-wp-_1698679908.txt
│   │   ├── select-wp-_1698679911.txt
│   │   ├── select-wp-_1698679922.txt
│   │   ├── select-wp-_1698679950.txt
│   │   ├── select-wp-_1698679956.txt
│   │   ├── select-wp-_1698679960.txt
│   │   ├── select-wp-_1698679985.txt
│   │   ├── select-wp-_1698679988.txt
│   │   ├── select-wp-_1698680305.txt
│   │   ├── set-names-_1698679872.txt
│   │   ├── set-names-_1698679874.txt
│   │   ├── set-names-_1698679875.txt
│   │   ├── set-names-_1698679876.txt
│   │   ├── set-names-_1698679883.txt
│   │   ├── set-names-_1698679884.txt
│   │   ├── set-names-_1698679886.txt
│   │   ├── set-names-_1698679887.txt
│   │   ├── set-names-_1698679889.txt
│   │   ├── set-names-_1698679897.txt
│   │   ├── set-names-_1698679900.txt
│   │   ├── set-names-_1698679907.txt
│   │   ├── set-names-_1698679910.txt
│   │   ├── set-names-_1698679911.txt
│   │   ├── set-names-_1698679917.txt
│   │   ├── set-names-_1698679918.txt
│   │   ├── set-names-_1698679919.txt
│   │   ├── set-names-_1698679922.txt
│   │   ├── set-names-_1698679923.txt
│   │   ├── set-names-_1698679924.txt
│   │   ├── set-names-_1698679926.txt
│   │   ├── set-names-_1698679928.txt
│   │   ├── set-names-_1698679931.txt
│   │   ├── set-names-_1698679935.txt
│   │   ├── set-names-_1698679936.txt
│   │   ├── set-names-_1698679940.txt
│   │   ├── set-names-_1698679949.txt
│   │   ├── set-names-_1698679950.txt
│   │   ├── set-names-_1698679952.txt
│   │   ├── set-names-_1698679953.txt
│   │   ├── set-names-_1698679954.txt
│   │   ├── set-names-_1698679955.txt
│   │   ├── set-names-_1698679956.txt
│   │   ├── set-names-_1698679960.txt
│   │   ├── set-names-_1698679965.txt
│   │   ├── set-names-_1698679972.txt
│   │   ├── set-names-_1698679984.txt
│   │   ├── set-names-_1698679985.txt
│   │   ├── set-names-_1698679987.txt
│   │   ├── set-names-_1698679988.txt
│   │   ├── set-names-_1698679989.txt
│   │   ├── set-names-_1698679991.txt
│   │   ├── set-names-_1698679992.txt
│   │   ├── set-names-_1698679995.txt
│   │   ├── set-names-_1698679999.txt
│   │   ├── set-names-_1698680063.txt
│   │   ├── set-names-_1698680183.txt
│   │   ├── set-names-_1698680304.txt
│   │   ├── show-full-_1698679874.txt
│   │   ├── show-full-_1698679875.txt
│   │   ├── show-full-_1698679884.txt
│   │   ├── show-full-_1698679886.txt
│   │   ├── show-full-_1698679897.txt
│   │   ├── show-full-_1698679908.txt
│   │   ├── show-full-_1698679917.txt
│   │   ├── show-full-_1698679918.txt
│   │   ├── show-full-_1698679923.txt
│   │   ├── show-full-_1698679926.txt
│   │   ├── show-full-_1698679936.txt
│   │   ├── show-full-_1698679954.txt
│   │   ├── show-full-_1698679965.txt
│   │   ├── show-full-_1698679972.txt
│   │   ├── show-full-_1698679996.txt
│   │   ├── update-wp-_1698679874.txt
│   │   ├── update-wp-_1698679884.txt
│   │   ├── update-wp-_1698679886.txt
│   │   ├── update-wp-_1698679917.txt
│   │   ├── update-wp-_1698679923.txt
│   │   ├── update-wp-_1698679926.txt
│   │   ├── update-wp-_1698679936.txt
│   │   ├── update-wp-_1698679965.txt
│   │   ├── update-wp-_1698679972.txt
│   │   └── update-wp-_1698679996.txt
│   ├── tools/
│   │   ├── php-cs-fixer.phar
│   │   └── phpunit.phar
│   └── verifyAgainstStubsTest.php
└── wp-includes/
    ├── cache.php
    ├── class-wp-object-cache.php
    ├── class-wpdb.php
    ├── l10n.php
    └── version.php
Download .txt
SYMBOL INDEX (384 symbols across 27 files)

FILE: pg4wp/driver_mysql.php
  function wpsqli_init (line 26) | function wpsqli_init()
  function wpsqli_real_connect (line 50) | function wpsqli_real_connect($connection, $hostname = null, $username = ...
  function wpsqli_close (line 66) | function wpsqli_close($connection)
  function wpsqli_ssl_set (line 89) | function wpsqli_ssl_set($connection, $key, $cert, $ca, $capath, $cipher)
  function wpsqli_get_client_info (line 105) | function wpsqli_get_client_info()
  function wpsqli_get_server_info (line 122) | function wpsqli_get_server_info($connection)
  function wpsqli_host_info (line 138) | function wpsqli_host_info($connection)
  function wpsqli_ping (line 157) | function wpsqli_ping($connection)
  function wpsqli_thread_id (line 173) | function wpsqli_thread_id($connection)
  function wpsqli_thread_safe (line 188) | function wpsqli_thread_safe()
  function wpsqli_stat (line 205) | function wpsqli_stat($connection)
  function wpsqli_options (line 224) | function wpsqli_options($connection, $option, $value)
  function wpsqli_connect_errno (line 240) | function wpsqli_connect_errno()
  function wpsqli_connect_error (line 257) | function wpsqli_connect_error()
  function wpsqli_autocommit (line 280) | function wpsqli_autocommit($connection, $mode)
  function wpsqli_begin_transaction (line 300) | function wpsqli_begin_transaction($connection, $flags = 0, $name = null)
  function wpsqli_commit (line 318) | function wpsqli_commit($connection, $flags = 0, $name = null)
  function wpsqli_rollback (line 338) | function wpsqli_rollback($connection, $flags = 0, $name = null)
  function wpsqli_select_db (line 359) | function wpsqli_select_db($connection, $database)
  function wpsqli_query (line 380) | function wpsqli_query($connection, $query, $result_mode = MYSQLI_STORE_R...
  function wpsqli_multi_query (line 401) | function wpsqli_multi_query($connection, $query)
  function wpsqli_prepare (line 419) | function wpsqli_prepare($connection, $query)
  function wpsqli_stmt_execute (line 436) | function wpsqli_stmt_execute($stmt)
  function wpsqli_stmt_bind_param (line 456) | function wpsqli_stmt_bind_param($stmt, $types, ...$vars)
  function wpsqli_stmt_bind_result (line 474) | function wpsqli_stmt_bind_result($stmt, &...$vars)
  function wpsqli_stmt_fetch (line 490) | function wpsqli_stmt_fetch($stmt)
  function wpsqli_stmt_close (line 506) | function wpsqli_stmt_close($stmt)
  function wpsqli_stmt_error (line 523) | function wpsqli_stmt_error($stmt)
  function wpsqli_stmt_errno (line 540) | function wpsqli_stmt_errno($stmt)
  function wpsqli_fetch_array (line 564) | function wpsqli_fetch_array($result, $mode = MYSQLI_BOTH)
  function wpsqli_fetch_object (line 588) | function wpsqli_fetch_object($result, $class = "stdClass", $constructor_...
  function wpsqli_fetch_row (line 608) | function wpsqli_fetch_row(mysqli_result $result): ?array
  function wpsqli_data_seek (line 629) | function wpsqli_data_seek(mysqli_result $result, int $row_number): bool
  function wpsqli_fetch_field (line 648) | function wpsqli_fetch_field($result)
  function wpsqli_num_fields (line 665) | function wpsqli_num_fields($result)
  function wpsqli_field_count (line 681) | function wpsqli_field_count($connection)
  function wpsqli_store_result (line 699) | function wpsqli_store_result($connection)
  function wpsqli_use_result (line 717) | function wpsqli_use_result($connection)
  function wpsqli_free_result (line 735) | function wpsqli_free_result($result)
  function wpsqli_more_results (line 754) | function wpsqli_more_results($connection)
  function wpsqli_next_result (line 772) | function wpsqli_next_result($connection)
  function wpsqli_is_resource (line 781) | function wpsqli_is_resource($object)
  function wpsqli_affected_rows (line 798) | function wpsqli_affected_rows($connection)
  function wpsqli_insert_id (line 817) | function wpsqli_insert_id($connection)
  function wpsqli_set_charset (line 835) | function wpsqli_set_charset($connection, $charset)
  function wpsqli_real_escape_string (line 854) | function wpsqli_real_escape_string($connection, $string)
  function wpsqli_error (line 873) | function wpsqli_error($connection)
  function wpsqli_errno (line 890) | function wpsqli_errno($connection)
  function wpsqli_report (line 907) | function wpsqli_report($flags)
  function wpsqli_info (line 925) | function wpsqli_info($connection)
  function wpsqli_stmt_init (line 942) | function wpsqli_stmt_init($connection)
  function wpsqli_poll (line 965) | function wpsqli_poll(&...$args)
  function wpsqli_reap_async_query (line 983) | function wpsqli_reap_async_query($connection)

FILE: pg4wp/driver_pgsql.php
  function wpsqli_init (line 33) | function wpsqli_init()
  function wpsqli_real_connect (line 62) | function wpsqli_real_connect(&$connection, $hostname = null, $username =...
  function wpsqli_select_db (line 127) | function wpsqli_select_db(&$connection, $database)
  function wpsqli_close (line 169) | function wpsqli_close(&$connection)
  function wpsqli_ssl_set (line 190) | function wpsqli_ssl_set(&$connection, $key, $cert, $ca, $capath, $cipher)
  function wpsqli_get_client_info (line 210) | function wpsqli_get_client_info()
  function wpsqli_get_server_info (line 228) | function wpsqli_get_server_info(&$connection)
  function wpsqli_host_info (line 247) | function wpsqli_host_info(&$connection)
  function wpsqli_ping (line 267) | function wpsqli_ping(&$connection)
  function wpsqli_thread_id (line 283) | function wpsqli_thread_id(&$connection)
  function wpsqli_thread_safe (line 299) | function wpsqli_thread_safe()
  function wpsqli_stat (line 317) | function wpsqli_stat(&$connection)
  function wpsqli_options (line 337) | function wpsqli_options(&$connection, $option, $value)
  function wpsqli_connect_errno (line 354) | function wpsqli_connect_errno()
  function wpsqli_connect_error (line 371) | function wpsqli_connect_error()
  function wpsqli_autocommit (line 398) | function wpsqli_autocommit(&$connection, $mode)
  function wpsqli_begin_transaction (line 420) | function wpsqli_begin_transaction(&$connection, $flags = 0, $name = null)
  function wpsqli_commit (line 440) | function wpsqli_commit(&$connection, $flags = 0, $name = null)
  function wpsqli_rollback (line 462) | function wpsqli_rollback(&$connection, $flags = 0, $name = null)
  function get_primary_key_for_table (line 469) | function get_primary_key_for_table(&$connection, $table)
  function wpsqli_query (line 511) | function wpsqli_query(&$connection, $query, $result_mode = 0)
  function wpsqli_multi_query (line 580) | function wpsqli_multi_query(&$connection, $query)
  function wpsqli_prepare (line 603) | function wpsqli_prepare(&$connection, $query)
  function wpsqli_stmt_execute (line 626) | function wpsqli_stmt_execute($stmt)
  function wpsqli_stmt_bind_param (line 653) | function wpsqli_stmt_bind_param($stmt, $types, ...$vars)
  function wpsqli_stmt_bind_result (line 677) | function wpsqli_stmt_bind_result($stmt, &...$vars)
  function wpsqli_stmt_fetch (line 699) | function wpsqli_stmt_fetch($stmt)
  function wpsqli_stmt_init (line 722) | function wpsqli_stmt_init(&$connection)
  function wpsqli_stmt_close (line 741) | function wpsqli_stmt_close($stmt)
  function wpsqli_stmt_error (line 764) | function wpsqli_stmt_error($stmt)
  function wpsqli_stmt_errno (line 787) | function wpsqli_stmt_errno($stmt)
  function wpsqli_fetch_array (line 819) | function wpsqli_fetch_array($result, $mode = PGSQL_BOTH)
  function wpsqli_fetch_object (line 854) | function wpsqli_fetch_object($result, $class = "stdClass", $constructor_...
  function wpsqli_fetch_row (line 874) | function wpsqli_fetch_row($result): ?array
  function wpsqli_data_seek (line 895) | function wpsqli_data_seek($result, int $row_number): bool
  function wpsqli_fetch_field (line 914) | function wpsqli_fetch_field($result)
  function wpsqli_num_fields (line 934) | function wpsqli_num_fields($result)
  function wpsqli_field_count (line 952) | function wpsqli_field_count(&$connection)
  function wpsqli_store_result (line 972) | function wpsqli_store_result(&$connection)
  function wpsqli_use_result (line 993) | function wpsqli_use_result(&$connection)
  function wpsqli_free_result (line 1013) | function wpsqli_free_result($result)
  function wpsqli_more_results (line 1032) | function wpsqli_more_results(&$connection)
  function wpsqli_next_result (line 1049) | function wpsqli_next_result(&$connection)
  function wpsqli_is_resource (line 1060) | function wpsqli_is_resource($object)
  function wpsqli_affected_rows (line 1077) | function wpsqli_affected_rows(&$connection)
  function wpsqli_get_list_of_sequences (line 1086) | function wpsqli_get_list_of_sequences(&$connection)
  function wpsqli_get_primary_sequence_for_table (line 1103) | function wpsqli_get_primary_sequence_for_table(&$connection, $table)
  function wpsqli_insert_id (line 1138) | function wpsqli_insert_id(&$connection = null)
  function wpsqli_set_charset (line 1190) | function wpsqli_set_charset(&$connection, $charset)
  function wpsqli_real_escape_string (line 1211) | function wpsqli_real_escape_string(&$connection, $string)
  function wpsqli_error (line 1232) | function wpsqli_error(&$connection)
  function wpsqli_errno (line 1250) | function wpsqli_errno(&$connection)
  function wpsqli_report (line 1273) | function wpsqli_report($flags)
  function wpsqli_info (line 1293) | function wpsqli_info(&$connection)
  function wpsqli_poll (line 1319) | function wpsqli_poll(&...$args)
  function wpsqli_reap_async_query (line 1340) | function wpsqli_reap_async_query(&$connection)

FILE: pg4wp/driver_pgsql_rewrite.php
  function createSQLRewriter (line 12) | function createSQLRewriter(string $sql): AbstractSQLRewriter
  function pg4wp_rewrite (line 30) | function pg4wp_rewrite($sql)
  function correctMetaValue (line 115) | function correctMetaValue($sql)
  function handleInterval (line 130) | function handleInterval($sql)
  function cleanAndCapitalize (line 145) | function cleanAndCapitalize($sql)
  function correctEmptyInStatements (line 174) | function correctEmptyInStatements($sql)
  function correctQuoting (line 188) | function correctQuoting($sql)

FILE: pg4wp/rewriters/AbstractSQLRewriter.php
  class AbstractSQLRewriter (line 3) | abstract class AbstractSQLRewriter
    method __construct (line 7) | public function __construct(string $sql)
    method rewrite (line 12) | abstract public function rewrite(): string;
    method original (line 14) | public function original(): string
    method type (line 19) | public function type(): string

FILE: pg4wp/rewriters/AlterTableSQLRewriter.php
  class AlterTableSQLRewriter (line 3) | class AlterTableSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 28) | public function rewrite(): string
    method rewriteAddIndex (line 67) | private function rewriteAddIndex(string $sql): string
    method rewriteChangeColumn (line 91) | private function rewriteChangeColumn(string $sql): string
    method rewriteAlterColumn (line 126) | private function rewriteAlterColumn(string $sql): string
    method rewriteAddColumn (line 142) | private function rewriteAddColumn(string $sql): string
    method rewriteAddKey (line 173) | private function rewriteAddKey(string $sql): string
    method rewriteDropIndex (line 195) | private function rewriteDropIndex(string $sql): string
    method rewriteDropPrimaryKey (line 208) | private function rewriteDropPrimaryKey(string $sql): string
    method rewrite_numeric_type (line 220) | private function rewrite_numeric_type($sql)
    method rewrite_columns_with_protected_names (line 267) | private function rewrite_columns_with_protected_names($sql)

FILE: pg4wp/rewriters/CreateTableSQLRewriter.php
  class CreateTableSQLRewriter (line 3) | class CreateTableSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 28) | public function rewrite(): string
    method rewrite_numeric_type (line 98) | private function rewrite_numeric_type($sql)
    method rewrite_columns_with_protected_names (line 145) | private function rewrite_columns_with_protected_names($sql)

FILE: pg4wp/rewriters/DeleteSQLRewriter.php
  class DeleteSQLRewriter (line 3) | class DeleteSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string

FILE: pg4wp/rewriters/DescribeSQLRewriter.php
  class DescribeSQLRewriter (line 3) | class DescribeSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string
    method extractTableName (line 18) | protected function extractTableName($sql)
    method generatePostgresDescribeTable (line 34) | public function generatePostgresDescribeTable($tableName, $schema = "p...

FILE: pg4wp/rewriters/DropTableSQLRewriter.php
  class DropTableSQLRewriter (line 3) | class DropTableSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string

FILE: pg4wp/rewriters/InsertSQLRewriter.php
  class InsertSQLRewriter (line 3) | class InsertSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string
    method findSemicolon (line 134) | private function findSemicolon($sql)

FILE: pg4wp/rewriters/OptimizeTableSQLRewriter.php
  class OptimizeTableSQLRewriter (line 3) | class OptimizeTableSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string

FILE: pg4wp/rewriters/ReplaceIntoSQLRewriter.php
  class ReplaceIntoSQLRewriter (line 3) | class ReplaceIntoSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string
    method findSemicolon (line 124) | private function findSemicolon($sql)

FILE: pg4wp/rewriters/SelectSQLRewriter.php
  class SelectSQLRewriter (line 3) | class SelectSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string
    method ensureOrderByInSelect (line 195) | protected function ensureOrderByInSelect(string $sql): string
    method ensureGroupByOrAggregate (line 280) | protected function ensureGroupByOrAggregate(string $sql): string
    method convertToPostgresLimitSyntax (line 357) | protected function convertToPostgresLimitSyntax($sql)
    method postgresTableSizeRewrite (line 376) | protected function postgresTableSizeRewrite($schema = 'public')

FILE: pg4wp/rewriters/SetNamesSQLRewriter.php
  class SetNamesSQLRewriter (line 3) | class SetNamesSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string

FILE: pg4wp/rewriters/ShowFullColumnsSQLRewriter.php
  class ShowFullColumnsSQLRewriter (line 3) | class ShowFullColumnsSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string
    method extractTableNameFromShowColumns (line 18) | protected function extractTableNameFromShowColumns($sql)
    method generatePostgresShowColumns (line 34) | public function generatePostgresShowColumns($tableName, $schema = "pub...

FILE: pg4wp/rewriters/ShowIndexSQLRewriter.php
  class ShowIndexSQLRewriter (line 3) | class ShowIndexSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string
    method extractVariableName (line 18) | protected function extractVariableName($sql)
    method generatePostgresShowIndexFrom (line 33) | public function generatePostgresShowIndexFrom($tableName)

FILE: pg4wp/rewriters/ShowTableStatusSQLRewriter.php
  class ShowTableStatusSQLRewriter (line 3) | class ShowTableStatusSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string
    method generatePostgresShowTableStatus (line 17) | public function generatePostgresShowTableStatus($schema = "public")

FILE: pg4wp/rewriters/ShowTablesSQLRewriter.php
  class ShowTablesSQLRewriter (line 3) | class ShowTablesSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string

FILE: pg4wp/rewriters/ShowVariablesSQLRewriter.php
  class ShowVariablesSQLRewriter (line 3) | class ShowVariablesSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string
    method extractVariableName (line 18) | protected function extractVariableName($sql)
    method generatePostgres (line 33) | public function generatePostgres($sql, $variableName)

FILE: pg4wp/rewriters/UpdateSQLRewriter.php
  class UpdateSQLRewriter (line 3) | class UpdateSQLRewriter extends AbstractSQLRewriter
    method rewrite (line 5) | public function rewrite(): string

FILE: tests/parseTest.php
  class parseTest (line 16) | final class parseTest extends TestCase
    method test_it_can_parse_a_theme_change_correctly (line 18) | public function test_it_can_parse_a_theme_change_correctly()
    method test_it_can_parse_a_page_creation_correctly (line 27) | public function test_it_can_parse_a_page_creation_correctly()
    method setUp (line 36) | protected function setUp(): void

FILE: tests/rewriteTest.php
  class rewriteTest (line 16) | final class rewriteTest extends TestCase
    method test_it_can_rewrite_users_admin_query (line 18) | public function test_it_can_rewrite_users_admin_query()
    method test_it_adds_group_by (line 28) | public function test_it_adds_group_by()
    method test_it_handles_auto_increment (line 37) | public function test_it_handles_auto_increment()
    method test_it_handles_auto_increment_without_null (line 77) | public function test_it_handles_auto_increment_without_null()
    method test_it_handles_numerics_without_auto_incrment_case_insensitively (line 99) | public function test_it_handles_numerics_without_auto_incrment_case_in...
    method test_it_handles_keys (line 123) | public function test_it_handles_keys()
    method test_it_handles_keys_without_unique (line 151) | public function test_it_handles_keys_without_unique()
    method test_it_does_not_remove_if_not_exists (line 193) | public function test_it_does_not_remove_if_not_exists()
    method test_it_removes_character_sets (line 222) | public function test_it_removes_character_sets()
    method test_it_handles_multiple_keys (line 266) | public function test_it_handles_multiple_keys()
    method test_it_removes_table_charsets (line 307) | public function test_it_removes_table_charsets()
    method test_it_can_create_keys_with_length (line 330) | public function test_it_can_create_keys_with_length()
    method test_it_can_create_double_keys_with_length (line 362) | public function test_it_can_create_double_keys_with_length()
    method test_it_will_handle_found_rows_on_queries_with_order_by_case (line 408) | public function test_it_will_handle_found_rows_on_queries_with_order_b...
    method test_it_will_append_returning_id_to_insert_statements (line 441) | public function test_it_will_append_returning_id_to_insert_statements()
    method test_it_can_handle_replacement_sql (line 467) | public function test_it_can_handle_replacement_sql()
    method test_it_doesnt_rewrite_when_it_doesnt_need_to (line 476) | public function test_it_doesnt_rewrite_when_it_doesnt_need_to()
    method test_it_handles_alter_tables_with_indexes (line 498) | public function test_it_handles_alter_tables_with_indexes()
    method test_it_handles_alter_tables_with_unique_indexes (line 513) | public function test_it_handles_alter_tables_with_unique_indexes()
    method test_it_rewrites_protected_column_names (line 527) | public function test_it_rewrites_protected_column_names()
    method test_it_rewrites_advanced_protected_column_names (line 549) | public function test_it_rewrites_advanced_protected_column_names()
    method test_it_doesnt_remove_single_quotes (line 590) | public function test_it_doesnt_remove_single_quotes()
    method test_it_can_handle_insert_sql_containing_nested_parathesis_with_numbers (line 604) | public function test_it_can_handle_insert_sql_containing_nested_parath...
    method test_it_rewrites_mediumints (line 657) | public function test_it_rewrites_mediumints()
    method test_it_rewrites_0CASTS (line 713) | public function test_it_rewrites_0CASTS()
    method test_it_rewrites_regexp (line 746) | public function test_it_rewrites_regexp()
    method test_it_rewrites_utc_timestamp_inserts (line 760) | public function test_it_rewrites_utc_timestamp_inserts()
    method test_it_rewrites_utc_timestamp_selects (line 774) | public function test_it_rewrites_utc_timestamp_selects()
    method test_it_quotes_reserved_columns (line 788) | public function test_it_quotes_reserved_columns()
    method setUp (line 849) | protected function setUp(): void
    method test_it_properly_uses_dynamic_table_prefix_for_delete_queries (line 861) | public function test_it_properly_uses_dynamic_table_prefix_for_delete_...

FILE: tests/verifyAgainstStubsTest.php
  class verifyAgainstStubsTest (line 16) | final class verifyAgainstStubsTest extends TestCase
    method test_verify_against_stubs (line 20) | public function test_verify_against_stubs()
    method setUp (line 29) | protected function setUp(): void

FILE: wp-includes/cache.php
  function wp_cache_init (line 21) | function wp_cache_init() {
  function wp_cache_add (line 41) | function wp_cache_add( $key, $data, $group = '', $expire = 0 ) {
  function wp_cache_add_multiple (line 62) | function wp_cache_add_multiple( array $data, $group = '', $expire = 0 ) {
  function wp_cache_replace (line 84) | function wp_cache_replace( $key, $data, $group = '', $expire = 0 ) {
  function wp_cache_set (line 108) | function wp_cache_set( $key, $data, $group = '', $expire = 0 ) {
  function wp_cache_set_multiple (line 129) | function wp_cache_set_multiple( array $data, $group = '', $expire = 0 ) {
  function wp_cache_get (line 151) | function wp_cache_get( $key, $group = '', $force = false, &$found = null...
  function wp_cache_get_multiple (line 172) | function wp_cache_get_multiple( $keys, $group = '', $force = false ) {
  function wp_cache_delete (line 190) | function wp_cache_delete( $key, $group = '' ) {
  function wp_cache_delete_multiple (line 209) | function wp_cache_delete_multiple( array $keys, $group = '' ) {
  function wp_cache_incr (line 229) | function wp_cache_incr( $key, $offset = 1, $group = '' ) {
  function wp_cache_decr (line 249) | function wp_cache_decr( $key, $offset = 1, $group = '' ) {
  function wp_cache_flush (line 265) | function wp_cache_flush() {
  function wp_cache_flush_runtime (line 280) | function wp_cache_flush_runtime() {
  function wp_cache_flush_group (line 298) | function wp_cache_flush_group( $group ) {
  function wp_cache_supports (line 314) | function wp_cache_supports( $feature ) {
  function wp_cache_close (line 342) | function wp_cache_close() {
  function wp_cache_add_global_groups (line 356) | function wp_cache_add_global_groups( $groups ) {
  function wp_cache_add_non_persistent_groups (line 369) | function wp_cache_add_non_persistent_groups( $groups ) {
  function wp_cache_switch_to_blog (line 385) | function wp_cache_switch_to_blog( $blog_id ) {
  function wp_cache_reset (line 409) | function wp_cache_reset() {

FILE: wp-includes/class-wp-object-cache.php
  class WP_Object_Cache (line 24) | #[AllowDynamicProperties]
    method __construct (line 80) | public function __construct() {
    method __get (line 93) | public function __get( $name ) {
    method __set (line 106) | public function __set( $name, $value ) {
    method __isset (line 118) | public function __isset( $name ) {
    method __unset (line 129) | public function __unset( $name ) {
    method is_valid_key (line 141) | protected function is_valid_key( $key ) {
    method _exists (line 179) | protected function _exists( $key, $group ) {
    method add (line 199) | public function add( $key, $data, $group = 'default', $expire = 0 ) {
    method add_multiple (line 236) | public function add_multiple( array $data, $group = '', $expire = 0 ) {
    method replace (line 260) | public function replace( $key, $data, $group = 'default', $expire = 0 ) {
    method set (line 302) | public function set( $key, $data, $group = 'default', $expire = 0 ) {
    method set_multiple (line 334) | public function set_multiple( array $data, $group = '', $expire = 0 ) {
    method get (line 363) | public function get( $key, $group = 'default', $force = false, &$found...
    method get_multiple (line 403) | public function get_multiple( $keys, $group = 'default', $force = fals...
    method delete (line 425) | public function delete( $key, $group = 'default', $deprecated = false ) {
    method delete_multiple (line 456) | public function delete_multiple( array $keys, $group = '' ) {
    method incr (line 477) | public function incr( $key, $offset = 1, $group = 'default' ) {
    method decr (line 520) | public function decr( $key, $offset = 1, $group = 'default' ) {
    method flush (line 559) | public function flush() {
    method flush_group (line 573) | public function flush_group( $group ) {
    method add_global_groups (line 586) | public function add_global_groups( $groups ) {
    method switch_to_blog (line 602) | public function switch_to_blog( $blog_id ) {
    method reset (line 615) | public function reset() {
    method stats (line 634) | public function stats() {

FILE: wp-includes/class-wpdb.php
  class wpdb (line 54) | #[AllowDynamicProperties]
    method __construct (line 752) | public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
    method __get (line 778) | public function __get( $name ) {
    method __set (line 794) | public function __set( $name, $value ) {
    method __isset (line 815) | public function __isset( $name ) {
    method __unset (line 826) | public function __unset( $name ) {
    method init_charset (line 835) | public function init_charset() {
    method determine_charset (line 876) | public function determine_charset( $charset, $collate ) {
    method set_charset (line 916) | public function set_charset( $dbh, $charset = null, $collate = null ) {
    method set_sql_mode (line 949) | public function set_sql_mode( $modes = array() ) {
    method set_prefix (line 1004) | public function set_prefix( $prefix, $set_table_names = true ) {
    method set_blog_id (line 1049) | public function set_blog_id( $blog_id, $network_id = 0 ) {
    method get_blog_prefix (line 1079) | public function get_blog_prefix( $blog_id = null ) {
    method tables (line 1128) | public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) {
    method select (line 1198) | public function select( $db, $dbh = null ) {
    method _weak_escape (line 1260) | public function _weak_escape( $data ) {
    method _real_escape (line 1277) | public function _real_escape( $data ) {
    method _escape (line 1307) | public function _escape( $data ) {
    method escape (line 1336) | public function escape( $data ) {
    method escape_by_ref (line 1364) | public function escape_by_ref( &$data ) {
    method quote_identifier (line 1378) | public function quote_identifier( $identifier ) {
    method _escape_identifier_value (line 1396) | private function _escape_identifier_value( $identifier ) {
    method prepare (line 1457) | public function prepare( $query, ...$args ) {
    method esc_like (line 1784) | public function esc_like( $text ) {
    method print_error (line 1798) | public function print_error( $str = '' ) {
    method show_errors (line 1872) | public function show_errors( $show = true ) {
    method hide_errors (line 1889) | public function hide_errors() {
    method suppress_errors (line 1907) | public function suppress_errors( $suppress = true ) {
    method flush (line 1918) | public function flush() {
    method db_connect (line 1953) | public function db_connect( $allow_bail = true ) {
    method parse_db_host (line 2070) | public function parse_db_host( $host ) {
    method check_connection (line 2121) | public function check_connection( $allow_bail = true ) {
    method query (line 2210) | public function query( $query ) {
    method _do_query (line 2343) | private function _do_query( $query ) {
    method log_query (line 2376) | public function log_query( $query, $query_time, $query_callstack, $que...
    method placeholder_escape (line 2409) | public function placeholder_escape() {
    method add_placeholder_escape (line 2440) | public function add_placeholder_escape( $query ) {
    method remove_placeholder_escape (line 2456) | public function remove_placeholder_escape( $query ) {
    method insert (line 2502) | public function insert( $table, $data, $format = null ) {
    method replace (line 2555) | public function replace( $table, $data, $format = null ) {
    method _insert_replace_helper (line 2584) | public function _insert_replace_helper( $table, $data, $format = null,...
    method update (line 2678) | public function update( $table, $data, $where, $format = null, $where_...
    method delete (line 2763) | public function delete( $table, $where, $where_format = null ) {
    method process_fields (line 2810) | protected function process_fields( $table, $data, $format ) {
    method process_field_formats (line 2873) | protected function process_field_formats( $data, $format ) {
    method process_field_charsets (line 2928) | protected function process_field_charsets( $data, $table ) {
    method process_field_lengths (line 2987) | protected function process_field_lengths( $data, $table ) {
    method get_var (line 3023) | public function get_var( $query = null, $x = 0, $y = 0 ) {
    method get_row (line 3057) | public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
    method get_col (line 3101) | public function get_col( $query = null, $x = 0 ) {
    method get_results (line 3138) | public function get_results( $query = null, $output = OBJECT ) {
    method get_table_charset (line 3201) | protected function get_table_charset( $table ) {
    method get_col_charset (line 3305) | public function get_col_charset( $table, $column ) {
    method get_col_length (line 3375) | public function get_col_length( $table, $column ) {
    method check_ascii (line 3464) | protected function check_ascii( $input_string ) {
    method check_safe_collation (line 3484) | protected function check_safe_collation( $query ) {
    method strip_invalid_text (line 3554) | protected function strip_invalid_text( $data ) {
    method strip_invalid_text_from_query (line 3706) | protected function strip_invalid_text_from_query( $query ) {
    method strip_invalid_text_for_column (line 3753) | public function strip_invalid_text_for_column( $table, $column, $value...
    method get_table_from_query (line 3791) | protected function get_table_from_query( $query ) {
    method load_col_info (line 3863) | protected function load_col_info() {
    method get_col_info (line 3887) | public function get_col_info( $info_type = 'name', $col_offset = -1 ) {
    method timer_start (line 3912) | public function timer_start() {
    method timer_stop (line 3924) | public function timer_stop() {
    method bail (line 3940) | public function bail( $message, $error_code = '500' ) {
    method close (line 3974) | public function close() {
    method check_database_version (line 3999) | public function check_database_version() {
    method supports_collation (line 4020) | public function supports_collation() {
    method get_charset_collate (line 4032) | public function get_charset_collate() {
    method has_cap (line 4068) | public function has_cap( $db_cap ) {
    method get_caller (line 4135) | public function get_caller() {
    method db_version (line 4146) | public function db_version() {
    method db_server_info (line 4157) | public function db_server_info() {

FILE: wp-includes/l10n.php
  function get_locale (line 30) | function get_locale() {
  function get_user_locale (line 94) | function get_user_locale( $user = 0 ) {
  function determine_locale (line 123) | function determine_locale() {
  function translate (line 184) | function translate( $text, $domain = 'default' ) {
  function before_last_bar (line 226) | function before_last_bar( $text ) {
  function translate_with_gettext_context (line 251) | function translate_with_gettext_context( $text, $context, $domain = 'def...
  function __ (line 296) | function __( $text, $domain = 'default' ) {
  function esc_attr__ (line 312) | function esc_attr__( $text, $domain = 'default' ) {
  function esc_html__ (line 329) | function esc_html__( $text, $domain = 'default' ) {
  function _e (line 342) | function _e( $text, $domain = 'default' ) {
  function esc_attr_e (line 360) | function esc_attr_e( $text, $domain = 'default' ) {
  function esc_html_e (line 378) | function esc_html_e( $text, $domain = 'default' ) {
  function _x (line 399) | function _x( $text, $context, $domain = 'default' ) {
  function _ex (line 413) | function _ex( $text, $context, $domain = 'default' ) {
  function esc_attr_x (line 431) | function esc_attr_x( $text, $context, $domain = 'default' ) {
  function esc_html_x (line 449) | function esc_html_x( $text, $context, $domain = 'default' ) {
  function _n (line 473) | function _n( $single, $plural, $number, $domain = 'default' ) {
  function _nx (line 532) | function _nx( $single, $plural, $number, $context, $domain = 'default' ) {
  function _n_noop (line 598) | function _n_noop( $singular, $plural, $domain = null ) {
  function _nx_noop (line 644) | function _nx_noop( $singular, $plural, $context, $domain = null ) {
  function translate_nooped_plural (line 683) | function translate_nooped_plural( $nooped_plural, $count, $domain = 'def...
  function load_textdomain (line 716) | function load_textdomain( $domain, $mofile, $locale = null ) {
  function unload_textdomain (line 824) | function unload_textdomain( $domain, $reloadable = false ) {
  function load_default_textdomain (line 892) | function load_default_textdomain( $locale = null ) {
  function load_plugin_textdomain (line 935) | function load_plugin_textdomain( $domain, $deprecated = false, $plugin_r...
  function load_muplugin_textdomain (line 983) | function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) {
  function load_theme_textdomain (line 1022) | function load_theme_textdomain( $domain, $path = false ) {
  function load_child_theme_textdomain (line 1067) | function load_child_theme_textdomain( $domain, $path = false ) {
  function load_script_textdomain (line 1089) | function load_script_textdomain( $handle, $domain = 'default', $path = '...
  function load_script_translations (line 1220) | function load_script_translations( $file, $handle, $domain ) {
  function _load_textdomain_just_in_time (line 1285) | function _load_textdomain_just_in_time( $domain ) {
  function get_translations_for_domain (line 1329) | function get_translations_for_domain( $domain ) {
  function is_textdomain_loaded (line 1355) | function is_textdomain_loaded( $domain ) {
  function translate_user_role (line 1380) | function translate_user_role( $name, $domain = 'default' ) {
  function get_available_languages (line 1397) | function get_available_languages( $dir = null ) {
  function wp_get_installed_translations (line 1433) | function wp_get_installed_translations( $type ) {
  function wp_get_pomo_file_data (line 1486) | function wp_get_pomo_file_data( $po_file ) {
  function wp_dropdown_languages (line 1535) | function wp_dropdown_languages( $args = array() ) {
  function is_rtl (line 1676) | function is_rtl() {
  function switch_to_locale (line 1694) | function switch_to_locale( $locale ) {
  function switch_to_user_locale (line 1715) | function switch_to_user_locale( $user_id ) {
  function restore_previous_locale (line 1735) | function restore_previous_locale() {
  function restore_current_locale (line 1755) | function restore_current_locale() {
  function is_locale_switched (line 1775) | function is_locale_switched() {
  function translate_settings_using_i18n_schema (line 1794) | function translate_settings_using_i18n_schema( $i18n_schema, $settings, ...
  function wp_get_list_item_separator (line 1835) | function wp_get_list_item_separator() {
  function wp_get_word_count_type (line 1857) | function wp_get_word_count_type() {
Condensed preview — 543 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,723K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/sql-rewriting-issue.md",
    "chars": 258,
    "preview": "---\nname: SQL Rewriting Issue\nabout: This is used for filing bugs or problems with PG4WP\ntitle: ''\nlabels: ''\nassignees:"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 37,
    "preview": "\nRelated Issues:\n - \n\nAdded Tests:\n -"
  },
  {
    "path": ".github/workflows/php.yml",
    "chars": 292,
    "preview": "name: PHP Composer\n\non:\n  push:\n    branches: [ \"v2\", \"v3\" ]\n  pull_request:\n    branches: [ \"v2\", \"v3\" ]\n\npermissions:\n"
  },
  {
    "path": ".gitignore",
    "chars": 46,
    "preview": "logs\n.phpunit.result.cache\n.php-cs-fixer.cache"
  },
  {
    "path": "license.md",
    "chars": 17885,
    "preview": "# GNU GENERAL PUBLIC LICENSE\n\nVersion 2, June 1991\n\n    Copyright (C) 1989, 1991 Free Software Foundation, Inc.  \n    51"
  },
  {
    "path": "pg4wp/core.php",
    "chars": 1222,
    "preview": "<?php\n/**\n * @package PostgreSQL_For_Wordpress\n * @version $Id$\n * @author\tHawk__, www.hawkix.net\n */\n\n/**\n* This file d"
  },
  {
    "path": "pg4wp/db.php",
    "chars": 1977,
    "preview": "<?php\n/*\nPlugin Name: PostgreSQL for WordPress (PG4WP)\nPlugin URI: https://github.com/PostgreSQL-For-Wordpress/postgresq"
  },
  {
    "path": "pg4wp/driver_mysql.php",
    "chars": 45392,
    "preview": "<?php\n\n/**\n* This file implements a mysql reference driver\n* This driver should do nothing different vs a standard insta"
  },
  {
    "path": "pg4wp/driver_pgsql.php",
    "chars": 58996,
    "preview": "<?php\n\ninclude_once PG4WP_ROOT . '/driver_pgsql_rewrite.php';\n\n/**\n* This file implements the postgreSQL driver\n* This f"
  },
  {
    "path": "pg4wp/driver_pgsql_rewrite.php",
    "chars": 6313,
    "preview": "<?php\n\n// Autoload function to automatically require rewriter classes from the \"rewriters\" folder\nspl_autoload_register("
  },
  {
    "path": "pg4wp/rewriters/AbstractSQLRewriter.php",
    "chars": 574,
    "preview": "<?php\n\nabstract class AbstractSQLRewriter\n{\n    protected string $originalSQL;\n\n    public function __construct(string $"
  },
  {
    "path": "pg4wp/rewriters/AlterTableSQLRewriter.php",
    "chars": 10157,
    "preview": "<?php\n\nclass AlterTableSQLRewriter extends AbstractSQLRewriter\n{\n    private $stringReplacements = [\n        ' tinytext'"
  },
  {
    "path": "pg4wp/rewriters/CreateTableSQLRewriter.php",
    "chars": 6321,
    "preview": "<?php\n\nclass CreateTableSQLRewriter extends AbstractSQLRewriter\n{\n    private $stringReplacements = [\n        ' tinytext"
  },
  {
    "path": "pg4wp/rewriters/DeleteSQLRewriter.php",
    "chars": 5315,
    "preview": "<?php\n\nclass DeleteSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        global "
  },
  {
    "path": "pg4wp/rewriters/DescribeSQLRewriter.php",
    "chars": 2838,
    "preview": "<?php\n\nclass DescribeSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        $sql "
  },
  {
    "path": "pg4wp/rewriters/DropTableSQLRewriter.php",
    "chars": 385,
    "preview": "<?php\n\nclass DropTableSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        $sql"
  },
  {
    "path": "pg4wp/rewriters/InsertSQLRewriter.php",
    "chars": 5987,
    "preview": "<?php\n\nclass InsertSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        global "
  },
  {
    "path": "pg4wp/rewriters/OptimizeTableSQLRewriter.php",
    "chars": 216,
    "preview": "<?php\n\nclass OptimizeTableSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        "
  },
  {
    "path": "pg4wp/rewriters/ReplaceIntoSQLRewriter.php",
    "chars": 5344,
    "preview": "<?php\n\nclass ReplaceIntoSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        gl"
  },
  {
    "path": "pg4wp/rewriters/SelectSQLRewriter.php",
    "chars": 15882,
    "preview": "<?php\n\nclass SelectSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        global "
  },
  {
    "path": "pg4wp/rewriters/SetNamesSQLRewriter.php",
    "chars": 150,
    "preview": "<?php\n\nclass SetNamesSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        retur"
  },
  {
    "path": "pg4wp/rewriters/ShowFullColumnsSQLRewriter.php",
    "chars": 2640,
    "preview": "<?php\n\nclass ShowFullColumnsSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n      "
  },
  {
    "path": "pg4wp/rewriters/ShowIndexSQLRewriter.php",
    "chars": 2284,
    "preview": "<?php\n\nclass ShowIndexSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        $sql"
  },
  {
    "path": "pg4wp/rewriters/ShowTableStatusSQLRewriter.php",
    "chars": 1574,
    "preview": "<?php\n\nclass ShowTableStatusSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n      "
  },
  {
    "path": "pg4wp/rewriters/ShowTablesSQLRewriter.php",
    "chars": 227,
    "preview": "<?php\n\nclass ShowTablesSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        $sc"
  },
  {
    "path": "pg4wp/rewriters/ShowVariablesSQLRewriter.php",
    "chars": 1620,
    "preview": "<?php\n\nclass ShowVariablesSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        "
  },
  {
    "path": "pg4wp/rewriters/UpdateSQLRewriter.php",
    "chars": 1011,
    "preview": "<?php\n\nclass UpdateSQLRewriter extends AbstractSQLRewriter\n{\n    public function rewrite(): string\n    {\n        global "
  },
  {
    "path": "phpunit.xml",
    "chars": 467,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"     \n  displayDe"
  },
  {
    "path": "readme.md",
    "chars": 3628,
    "preview": "## PostgreSQL for WordPress (PG4WP) \n\n### Description \n\nPostgreSQL for WordPress (PG4WP) gives you the possibility to in"
  },
  {
    "path": "tests/parseTest.php",
    "chars": 1892,
    "preview": "<?php\n\ndeclare(strict_types=1);\nuse PHPUnit\\Framework\\TestCase;\n\nif (!defined('ABSPATH')) {\n    define('ABSPATH', __DIR_"
  },
  {
    "path": "tests/rewriteTest.php",
    "chars": 39926,
    "preview": "<?php\n\ndeclare(strict_types=1);\nuse PHPUnit\\Framework\\TestCase;\n\nif (!defined('ABSPATH')) {\n    define('ABSPATH', __DIR_"
  },
  {
    "path": "tests/stubs/delete-fro_1698679875.txt",
    "chars": 314,
    "preview": "{\"mysql\":\"DELETE FROM `wp_sitemeta` WHERE `meta_key` = '_site_transient_timeout_wp_remote_block_patterns_03fe7d7ccb04346"
  },
  {
    "path": "tests/stubs/delete-fro_1698679877.txt",
    "chars": 298,
    "preview": "{\"mysql\":\"DELETE FROM `wp_sitemeta` WHERE `meta_key` = '_site_transient_wp_remote_block_patterns_0dc4db57500f00dee60778d"
  },
  {
    "path": "tests/stubs/delete-fro_1698679878.txt",
    "chars": 314,
    "preview": "{\"mysql\":\"DELETE FROM `wp_sitemeta` WHERE `meta_key` = '_site_transient_timeout_wp_remote_block_patterns_0dc4db57500f00d"
  },
  {
    "path": "tests/stubs/delete-fro_1698679918.txt",
    "chars": 314,
    "preview": "{\"mysql\":\"DELETE FROM `wp_sitemeta` WHERE `meta_key` = '_site_transient_timeout_wp_remote_block_patterns_03fe7d7ccb04346"
  },
  {
    "path": "tests/stubs/delete-fro_1698679920.txt",
    "chars": 314,
    "preview": "{\"mysql\":\"DELETE FROM `wp_sitemeta` WHERE `meta_key` = '_site_transient_timeout_wp_remote_block_patterns_0dc4db57500f00d"
  },
  {
    "path": "tests/stubs/delete-fro_1698679954.txt",
    "chars": 298,
    "preview": "{\"mysql\":\"DELETE FROM `wp_sitemeta` WHERE `meta_key` = '_site_transient_wp_remote_block_patterns_0dc4db57500f00dee60778d"
  },
  {
    "path": "tests/stubs/delete-fro_1698679955.txt",
    "chars": 314,
    "preview": "{\"mysql\":\"DELETE FROM `wp_sitemeta` WHERE `meta_key` = '_site_transient_timeout_wp_remote_block_patterns_0dc4db57500f00d"
  },
  {
    "path": "tests/stubs/insert-int_1698679874.txt",
    "chars": 242,
    "preview": "{\"mysql\":\"INSERT INTO `wp_postmeta` (`post_id`, `meta_key`, `meta_value`) VALUES (55, '_edit_lock', '1698679874:1')\",\"po"
  },
  {
    "path": "tests/stubs/insert-int_1698679877.txt",
    "chars": 781,
    "preview": "{\"mysql\":\"INSERT INTO `wp_sitemeta` (`site_id`, `meta_key`, `meta_value`) VALUES (1, '_site_transient_wp_remote_block_pa"
  },
  {
    "path": "tests/stubs/insert-int_1698679878.txt",
    "chars": 781,
    "preview": "{\"mysql\":\"INSERT INTO `wp_sitemeta` (`site_id`, `meta_key`, `meta_value`) VALUES (1, '_site_transient_wp_remote_block_pa"
  },
  {
    "path": "tests/stubs/insert-int_1698679884.txt",
    "chars": 1123,
    "preview": "{\"mysql\":\"INSERT INTO `wp_posts` (`post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_content_filtered`, "
  },
  {
    "path": "tests/stubs/insert-int_1698679897.txt",
    "chars": 583,
    "preview": "{\"mysql\":\"INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('category_children', 'a:0:{}', 'y"
  },
  {
    "path": "tests/stubs/insert-int_1698679908.txt",
    "chars": 276,
    "preview": "{\"mysql\":\"INSERT INTO `wp_term_taxonomy` (`term_id`, `taxonomy`, `description`, `parent`, `count`) VALUES (3, 'post_tag'"
  },
  {
    "path": "tests/stubs/insert-int_1698679917.txt",
    "chars": 242,
    "preview": "{\"mysql\":\"INSERT INTO `wp_postmeta` (`post_id`, `meta_key`, `meta_value`) VALUES (57, '_edit_lock', '1698679917:1')\",\"po"
  },
  {
    "path": "tests/stubs/insert-int_1698679920.txt",
    "chars": 781,
    "preview": "{\"mysql\":\"INSERT INTO `wp_sitemeta` (`site_id`, `meta_key`, `meta_value`) VALUES (1, '_site_transient_wp_remote_block_pa"
  },
  {
    "path": "tests/stubs/insert-int_1698679923.txt",
    "chars": 1117,
    "preview": "{\"mysql\":\"INSERT INTO `wp_posts` (`post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_content_filtered`, "
  },
  {
    "path": "tests/stubs/insert-int_1698679936.txt",
    "chars": 1195,
    "preview": "{\"mysql\":\"INSERT INTO `wp_comments` (`comment_post_ID`, `comment_author_IP`, `comment_author`, `comment_author_email`, `"
  },
  {
    "path": "tests/stubs/insert-int_1698679954.txt",
    "chars": 781,
    "preview": "{\"mysql\":\"INSERT INTO `wp_sitemeta` (`site_id`, `meta_key`, `meta_value`) VALUES (1, '_site_transient_wp_remote_block_pa"
  },
  {
    "path": "tests/stubs/insert-int_1698679955.txt",
    "chars": 781,
    "preview": "{\"mysql\":\"INSERT INTO `wp_sitemeta` (`site_id`, `meta_key`, `meta_value`) VALUES (1, '_site_transient_wp_remote_block_pa"
  },
  {
    "path": "tests/stubs/insert-int_1698679965.txt",
    "chars": 8361,
    "preview": "{\"mysql\":\"INSERT INTO `wp_posts` (`post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_content_filtered`, "
  },
  {
    "path": "tests/stubs/insert-int_1698679972.txt",
    "chars": 8345,
    "preview": "{\"mysql\":\"INSERT INTO `wp_posts` (`post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_content_filtered`, "
  },
  {
    "path": "tests/stubs/select-aut_1698679874.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT autoload FROM wp_options WHERE option_name = '_transient_is_multi_author'\",\"postgresql\":\"SELECT autoloa"
  },
  {
    "path": "tests/stubs/select-aut_1698679884.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT autoload FROM wp_options WHERE option_name = '_transient_is_multi_author'\",\"postgresql\":\"SELECT autoloa"
  },
  {
    "path": "tests/stubs/select-aut_1698679897.txt",
    "chars": 170,
    "preview": "{\"mysql\":\"SELECT autoload FROM wp_options WHERE option_name = 'category_children'\",\"postgresql\":\"SELECT autoload FROM wp"
  },
  {
    "path": "tests/stubs/select-aut_1698679908.txt",
    "chars": 170,
    "preview": "{\"mysql\":\"SELECT autoload FROM wp_options WHERE option_name = 'post_tag_children'\",\"postgresql\":\"SELECT autoload FROM wp"
  },
  {
    "path": "tests/stubs/select-aut_1698679917.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT autoload FROM wp_options WHERE option_name = '_transient_is_multi_author'\",\"postgresql\":\"SELECT autoloa"
  },
  {
    "path": "tests/stubs/select-aut_1698679923.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT autoload FROM wp_options WHERE option_name = '_transient_is_multi_author'\",\"postgresql\":\"SELECT autoloa"
  },
  {
    "path": "tests/stubs/select-aut_1698679965.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT autoload FROM wp_options WHERE option_name = '_transient_is_multi_author'\",\"postgresql\":\"SELECT autoloa"
  },
  {
    "path": "tests/stubs/select-aut_1698679972.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT autoload FROM wp_options WHERE option_name = '_transient_is_multi_author'\",\"postgresql\":\"SELECT autoloa"
  },
  {
    "path": "tests/stubs/select-blo_1698679989.txt",
    "chars": 227,
    "preview": "{\"mysql\":\"SELECT blog_id, meta_key, meta_value FROM wp_blogmeta WHERE blog_id IN (1) ORDER BY meta_id ASC\",\"postgresql\":"
  },
  {
    "path": "tests/stubs/select-com_1698679872.txt",
    "chars": 401,
    "preview": "{\"mysql\":\"SELECT comment_post_ID, COUNT(comment_ID) as num_comments FROM wp_comments WHERE comment_post_ID IN ( '51', '1"
  },
  {
    "path": "tests/stubs/select-com_1698679886.txt",
    "chars": 413,
    "preview": "{\"mysql\":\"SELECT comment_post_ID, COUNT(comment_ID) as num_comments FROM wp_comments WHERE comment_post_ID IN ( '55', '5"
  },
  {
    "path": "tests/stubs/select-com_1698679936.txt",
    "chars": 540,
    "preview": "{\"mysql\":\"SELECT comment_ID FROM wp_comments WHERE comment_post_ID = 55 AND comment_parent = '0' AND comment_approved !="
  },
  {
    "path": "tests/stubs/select-cou_1698679872.txt",
    "chars": 564,
    "preview": "{\"mysql\":\"SELECT COUNT( 1 )\\n\\t\\t\\t\\tFROM wp_posts\\n\\t\\t\\t\\tWHERE post_type = 'post'\\n\\t\\t\\t\\tAND post_status NOT IN ( '"
  },
  {
    "path": "tests/stubs/select-cou_1698679874.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( comment_approved = 'post-trashed' )\\n\\t\\t\\t\\n"
  },
  {
    "path": "tests/stubs/select-cou_1698679884.txt",
    "chars": 186,
    "preview": "{\"mysql\":\"SELECT COUNT(*) FROM wp_postmeta WHERE meta_key = '_encloseme' AND post_id = 55\",\"postgresql\":\"SELECT COUNT(*)"
  },
  {
    "path": "tests/stubs/select-cou_1698679886.txt",
    "chars": 564,
    "preview": "{\"mysql\":\"SELECT COUNT( 1 )\\n\\t\\t\\t\\tFROM wp_posts\\n\\t\\t\\t\\tWHERE post_type = 'post'\\n\\t\\t\\t\\tAND post_status NOT IN ( '"
  },
  {
    "path": "tests/stubs/select-cou_1698679889.txt",
    "chars": 346,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_i"
  },
  {
    "path": "tests/stubs/select-cou_1698679900.txt",
    "chars": 346,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_i"
  },
  {
    "path": "tests/stubs/select-cou_1698679910.txt",
    "chars": 564,
    "preview": "{\"mysql\":\"SELECT COUNT( 1 )\\n\\t\\t\\t\\tFROM wp_posts\\n\\t\\t\\t\\tWHERE post_type = 'page'\\n\\t\\t\\t\\tAND post_status NOT IN ( '"
  },
  {
    "path": "tests/stubs/select-cou_1698679917.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( comment_approved = 'post-trashed' )\\n\\t\\t\\t\\n"
  },
  {
    "path": "tests/stubs/select-cou_1698679926.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( comment_approved = 'post-trashed' )\\n\\t\\t\\t\\n"
  },
  {
    "path": "tests/stubs/select-cou_1698679929.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( comment_approved = 'post-trashed' )\\n\\t\\t\\t\\n"
  },
  {
    "path": "tests/stubs/select-cou_1698679931.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( comment_approved = 'post-trashed' )\\n\\t\\t\\t\\n"
  },
  {
    "path": "tests/stubs/select-cou_1698679936.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( comment_approved = 'post-trashed' )\\n\\t\\t\\t\\n"
  },
  {
    "path": "tests/stubs/select-cou_1698679941.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( comment_approved = 'post-trashed' )\\n\\t\\t\\t\\n"
  },
  {
    "path": "tests/stubs/select-cou_1698679949.txt",
    "chars": 378,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( ( comment_approved = '0' OR comment_approved "
  },
  {
    "path": "tests/stubs/select-cou_1698679952.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( comment_approved = 'post-trashed' )\\n\\t\\t\\t\\n"
  },
  {
    "path": "tests/stubs/select-cou_1698679955.txt",
    "chars": 346,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_i"
  },
  {
    "path": "tests/stubs/select-cou_1698679965.txt",
    "chars": 498,
    "preview": "{\"mysql\":\"SELECT COUNT(*) FROM wp_term_relationships, wp_posts WHERE wp_posts.ID = wp_term_relationships.object_id AND p"
  },
  {
    "path": "tests/stubs/select-cou_1698679972.txt",
    "chars": 498,
    "preview": "{\"mysql\":\"SELECT COUNT(*) FROM wp_term_relationships, wp_posts WHERE wp_posts.ID = wp_term_relationships.object_id AND p"
  },
  {
    "path": "tests/stubs/select-cou_1698679984.txt",
    "chars": 378,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT  COUNT(*)\\n\\t\\t\\tFROM wp_comments \\n\\t\\t\\tWHERE ( ( comment_approved = '0' OR comment_approved "
  },
  {
    "path": "tests/stubs/select-dis_1698679872.txt",
    "chars": 680,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679874.txt",
    "chars": 441,
    "preview": "{\"mysql\":\"SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month\\n\\t\\t\\t\\tFROM wp_posts\\n\\t\\t\\t\\tWHERE p"
  },
  {
    "path": "tests/stubs/select-dis_1698679876.txt",
    "chars": 718,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679884.txt",
    "chars": 636,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt ON t.term_id = "
  },
  {
    "path": "tests/stubs/select-dis_1698679885.txt",
    "chars": 718,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679886.txt",
    "chars": 680,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679910.txt",
    "chars": 680,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679917.txt",
    "chars": 441,
    "preview": "{\"mysql\":\"SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month\\n\\t\\t\\t\\tFROM wp_posts\\n\\t\\t\\t\\tWHERE p"
  },
  {
    "path": "tests/stubs/select-dis_1698679929.txt",
    "chars": 664,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679931.txt",
    "chars": 718,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679936.txt",
    "chars": 718,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679941.txt",
    "chars": 664,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679949.txt",
    "chars": 748,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679952.txt",
    "chars": 441,
    "preview": "{\"mysql\":\"SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month\\n\\t\\t\\t\\tFROM wp_posts\\n\\t\\t\\t\\tWHERE p"
  },
  {
    "path": "tests/stubs/select-dis_1698679955.txt",
    "chars": 748,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679965.txt",
    "chars": 664,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679972.txt",
    "chars": 664,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-dis_1698679984.txt",
    "chars": 748,
    "preview": "{\"mysql\":\"\\n\\t\\t\\tSELECT DISTINCT t.term_id, tr.object_id\\n\\t\\t\\tFROM wp_terms AS t  INNER JOIN wp_term_taxonomy AS tt O"
  },
  {
    "path": "tests/stubs/select-fro_1698679872.txt",
    "chars": 120,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 11 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 11 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679873.txt",
    "chars": 118,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 7 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 7 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679874.txt",
    "chars": 495,
    "preview": "{\"mysql\":\"\\n\\t\\tSELECT *\\n\\t\\tFROM wp_posts\\n\\t\\tWHERE post_parent = 55\\n\\t\\tAND post_type = 'revision'\\n\\t\\tAND post_st"
  },
  {
    "path": "tests/stubs/select-fro_1698679875.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679876.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679883.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679884.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679886.txt",
    "chars": 120,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 55 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 55 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679887.txt",
    "chars": 118,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 7 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 7 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679889.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679897.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679900.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679907.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679910.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679911.txt",
    "chars": 118,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 3 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 3 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679917.txt",
    "chars": 495,
    "preview": "{\"mysql\":\"\\n\\t\\tSELECT *\\n\\t\\tFROM wp_posts\\n\\t\\tWHERE post_parent = 57\\n\\t\\tAND post_type = 'revision'\\n\\t\\tAND post_st"
  },
  {
    "path": "tests/stubs/select-fro_1698679918.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679919.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679922.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679923.txt",
    "chars": 120,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 58 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 58 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679924.txt",
    "chars": 120,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 57 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 57 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679926.txt",
    "chars": 120,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 57 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 57 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679929.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679931.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679935.txt",
    "chars": 114,
    "preview": "{\"mysql\":\"SELECT * FROM wp_blogs WHERE blog_id IN (1)\",\"postgresql\":\"SELECT * FROM wp_blogs WHERE blog_id IN (1)\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679936.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679940.txt",
    "chars": 114,
    "preview": "{\"mysql\":\"SELECT * FROM wp_blogs WHERE blog_id IN (1)\",\"postgresql\":\"SELECT * FROM wp_blogs WHERE blog_id IN (1)\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679941.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679949.txt",
    "chars": 118,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 2 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 2 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679950.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679952.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679954.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679955.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679956.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679960.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679965.txt",
    "chars": 120,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 59 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 59 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679972.txt",
    "chars": 120,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 60 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 60 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679984.txt",
    "chars": 118,
    "preview": "{\"mysql\":\"SELECT * FROM wp_posts WHERE ID = 2 LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_posts WHERE \\\"ID\\\" = 2 LIMIT 1\"}"
  },
  {
    "path": "tests/stubs/select-fro_1698679985.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679987.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679988.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679989.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679991.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679992.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679996.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698679999.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698680063.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698680183.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-fro_1698680305.txt",
    "chars": 140,
    "preview": "{\"mysql\":\"SELECT * FROM wp_users WHERE user_login = 'root' LIMIT 1\",\"postgresql\":\"SELECT * FROM wp_users WHERE user_logi"
  },
  {
    "path": "tests/stubs/select-id-_1698679924.txt",
    "chars": 333,
    "preview": "{\"mysql\":\"\\n\\t\\tSELECT ID, post_name, post_parent, post_type\\n\\t\\tFROM wp_posts\\n\\t\\tWHERE post_name IN ('test-page')\\n\\"
  },
  {
    "path": "tests/stubs/select-id-_1698679926.txt",
    "chars": 333,
    "preview": "{\"mysql\":\"\\n\\t\\tSELECT ID, post_name, post_parent, post_type\\n\\t\\tFROM wp_posts\\n\\t\\tWHERE post_name IN ('test-page')\\n\\"
  },
  {
    "path": "tests/stubs/select-met_1698679872.txt",
    "chars": 220,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'duplicate_post_show_notice' AND site_id = 1\",\"postgresql\""
  },
  {
    "path": "tests/stubs/select-met_1698679874.txt",
    "chars": 202,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'wpmu_upgrade_site' AND site_id = 1\",\"postgresql\":\"SELECT "
  },
  {
    "path": "tests/stubs/select-met_1698679875.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679876.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679877.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"SELECT meta_id FROM wp_sitemeta WHERE meta_key = '_site_transient_wp_remote_block_patterns_0dc4db57500f00dee60"
  },
  {
    "path": "tests/stubs/select-met_1698679878.txt",
    "chars": 330,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = '_site_transient_timeout_wp_remote_block_patterns_0dc4db57"
  },
  {
    "path": "tests/stubs/select-met_1698679883.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679884.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679886.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'user_count' AND site_id = 1\",\"postgresql\":\"SELECT meta_va"
  },
  {
    "path": "tests/stubs/select-met_1698679887.txt",
    "chars": 220,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'duplicate_post_show_notice' AND site_id = 1\",\"postgresql\""
  },
  {
    "path": "tests/stubs/select-met_1698679889.txt",
    "chars": 202,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'wpmu_upgrade_site' AND site_id = 1\",\"postgresql\":\"SELECT "
  },
  {
    "path": "tests/stubs/select-met_1698679897.txt",
    "chars": 220,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'duplicate_post_show_notice' AND site_id = 1\",\"postgresql\""
  },
  {
    "path": "tests/stubs/select-met_1698679900.txt",
    "chars": 202,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'wpmu_upgrade_site' AND site_id = 1\",\"postgresql\":\"SELECT "
  },
  {
    "path": "tests/stubs/select-met_1698679907.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679908.txt",
    "chars": 220,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'duplicate_post_show_notice' AND site_id = 1\",\"postgresql\""
  },
  {
    "path": "tests/stubs/select-met_1698679910.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'user_count' AND site_id = 1\",\"postgresql\":\"SELECT meta_va"
  },
  {
    "path": "tests/stubs/select-met_1698679911.txt",
    "chars": 220,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'duplicate_post_show_notice' AND site_id = 1\",\"postgresql\""
  },
  {
    "path": "tests/stubs/select-met_1698679917.txt",
    "chars": 202,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'wpmu_upgrade_site' AND site_id = 1\",\"postgresql\":\"SELECT "
  },
  {
    "path": "tests/stubs/select-met_1698679918.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679919.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679920.txt",
    "chars": 330,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = '_site_transient_timeout_wp_remote_block_patterns_0dc4db57"
  },
  {
    "path": "tests/stubs/select-met_1698679922.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679923.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679924.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679926.txt",
    "chars": 184,
    "preview": "{\"mysql\":\"SELECT meta_id FROM wp_postmeta WHERE meta_key = '_edit_lock' AND post_id = 57\",\"postgresql\":\"SELECT meta_id F"
  },
  {
    "path": "tests/stubs/select-met_1698679929.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679931.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679935.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679936.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679940.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679949.txt",
    "chars": 222,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_space_check_disabled' AND site_id = 1\",\"postgresql"
  },
  {
    "path": "tests/stubs/select-met_1698679950.txt",
    "chars": 220,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'duplicate_post_show_notice' AND site_id = 1\",\"postgresql\""
  },
  {
    "path": "tests/stubs/select-met_1698679952.txt",
    "chars": 202,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'wpmu_upgrade_site' AND site_id = 1\",\"postgresql\":\"SELECT "
  },
  {
    "path": "tests/stubs/select-met_1698679954.txt",
    "chars": 308,
    "preview": "{\"mysql\":\"SELECT meta_id FROM wp_sitemeta WHERE meta_key = '_site_transient_wp_remote_block_patterns_0dc4db57500f00dee60"
  },
  {
    "path": "tests/stubs/select-met_1698679955.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679956.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679960.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679965.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679972.txt",
    "chars": 200,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_filetypes' AND site_id = 1\",\"postgresql\":\"SELECT m"
  },
  {
    "path": "tests/stubs/select-met_1698679984.txt",
    "chars": 222,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'upload_space_check_disabled' AND site_id = 1\",\"postgresql"
  },
  {
    "path": "tests/stubs/select-met_1698679985.txt",
    "chars": 220,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'duplicate_post_show_notice' AND site_id = 1\",\"postgresql\""
  },
  {
    "path": "tests/stubs/select-met_1698679987.txt",
    "chars": 188,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'blog_count' AND site_id = 1\",\"postgresql\":\"SELECT meta_va"
  },
  {
    "path": "tests/stubs/select-met_1698679988.txt",
    "chars": 220,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'duplicate_post_show_notice' AND site_id = 1\",\"postgresql\""
  },
  {
    "path": "tests/stubs/select-met_1698679989.txt",
    "chars": 214,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'auto_core_update_failed' AND site_id = 1\",\"postgresql\":\"S"
  },
  {
    "path": "tests/stubs/select-met_1698679991.txt",
    "chars": 214,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'auto_core_update_failed' AND site_id = 1\",\"postgresql\":\"S"
  },
  {
    "path": "tests/stubs/select-met_1698679992.txt",
    "chars": 598,
    "preview": "{\"mysql\":\"SELECT meta_key, meta_value FROM wp_sitemeta WHERE meta_key IN ('site_name', 'siteurl', 'active_sitewide_plugi"
  },
  {
    "path": "tests/stubs/select-met_1698679993.txt",
    "chars": 214,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'auto_core_update_failed' AND site_id = 1\",\"postgresql\":\"S"
  },
  {
    "path": "tests/stubs/select-met_1698679996.txt",
    "chars": 206,
    "preview": "{\"mysql\":\"SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'auto_update_plugins' AND site_id = 1\",\"postgresql\":\"SELEC"
  }
]

// ... and 343 more files (download for full content)

About this extraction

This page contains the full source code of the kevinoid/postgresql-for-wordpress GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 543 files (5.1 MB), approximately 1.4M tokens, and a symbol index with 384 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!