mirror of https://github.com/sysown/proxysql
docs/passthrough-auth-spec
feature/aws-rds-monitor
v3.0_fix_ci-mysqlx-cache-and-soak
GH-Actions
v3.0
v3.0_fix_codecov-coverage-path-prefix
issue-1288-load-mysql-variables-feedback
ci/fix-pgsql-socket-g1-cache-key
v3.0_fix_ci-mysqlx-fetch-depth
cleanup/drop-unreachable-port-defaults
feature/pgsql-native-backend-protocol
fix/pgsql-unix-socket
ci-pgsql-socket-g1
v3.0_fix_coverage-gcov-prefix-strip
fix/pgsql-omit-port-zero
aws-rds-bg
fix/jemalloc-page-size-auto-detect
feature/ci-codecov-tap-all-groups-callers
fix/run-tests-backtick-leak
ci/zstd-level-15
feature/ci-codecov-tap-all-groups-callees
v3.0_partition-fairness
feature/ci-codecov-tap-legacy-g2
v3.0_partition-gate
fix/ci-cache-restore-path
v3.0_fix-stale-pause-until
feature/perf-improvements-test2
fix/kill-proxysqlgenai-build-flag
feat/passthrough-auth
ci-trigger-tolerate-cleanup-401
fix/5790-mariadb-collation-255
fix/parsersql-1.0.3-pg-set-fixes
issue_5639
pgsql_dns_cache
fix/5755-followup-typecast-digest-fixtures
v3.0_merge-5776-5784
v3.0_latency_consistency_improvement
fix/galera-g5-cluster-start
fix/ghcr-pull-retry
v3.0_cap_violation_5767
ci-mariadb10-galera-GH-Actions
ci/fix-gr-g5-cluster-start
ci-mysql84-gr-g1-g9-GH-Actions
perf/pull-ci-base-from-ghcr
fix/split-test-groups
fix/rename-set-parser-workflow
gh-actions/add-set-parser-algorithm-3-g1
fix/4760-advertise-lenenc-auth-capability
feature/mysqlx-stack-consolidated
feature/mysqlx-asan-coverage-docker-isolation
fix/ci-unit-tests-tsan-project-name
feature/mysqlx-tsan-v3-companion
feature/ci-builds-add-tsan-matrix
ci-reduce-polling-interval
feature/mysqlx-tsan-workflow-only
feature/mysqlx-ci-validation-workflows
feature/mysqlx-test-leak-cleanup
feature/mysqlx-behavioural-tap
feature/mysqlx-parity-cleanup
ci-g5-enable-cluster
feature/mysqlx-tls-passthrough
feature/mysqlx-asymmetric-tls
feature/mysqlx-state-machines
feature/build-tsan-plumbing
feature/mysqlx-observability-p0
fix/mysqlx-review-findings
v3.0-test-ci
ci/fix-mysql-apt-key-expired-v2
ci/fix-mysql-apt-key-expired
mariadb-rpl-helper
fix-fc-parsing
ci/fix-upload-artifact-eacces
ci/fix-cache-prune-permissions
ci/shrink-test-cache
ci/fix-tap-build-target
ci/gh-actions-readme-pointer
ci/fix-mysql84-infradb-label
ci/add-missing-group-reusables
infra-mysql57-binlog
feature/pgbouncer-compat
v3.0_pgsql_sslkeylog_5281
fix/5554-resolution-family-limitation
fix/3p-ci-error-handling
v3.0-5493
v3.0-ci260322_cluster
copilot/extract-server-selection-algorithm
copilot/extract-health-state-logic
copilot/extract-query-rule-matching-logic
copilot/extract-connection-pool-logic
v3.0-set_parser_v3
feature/arm-builds
release-notes-3.0.6-4.0.6-draft
v3.0.6-add-tap-test_stats_table_check
v2.7.3-test260221
v4.0-mcp-stats
copilot/uninstall-amazon-linux-2023
fix-prometheus-labels-test
tap-mcp-client
agent-skill-tap-test
v4.0-tsdb1
v3.0-fix_5256
gh-pages
feature/modern-docs
v4.0
v4.0-fix-vec-search
v4.0_rag_sys_prompt
v4.0_rag_mcp
v4.0-tsdb
feature/v4-docs-init
otel_system_libs
otel_clean
v3.0-5288
otel
otel_2
fix/postgresql-cluster-sync
v3.0-releate_notes_scripts_fixes
test_gh-actions_triggers
postgresql-digest-testing-improvement
v3.0_select_auto_commit
v3.0-5218
fix-5221
fix/5186-proxysql-stop-admin-crash
v3.0-4951
add-claude-github-actions-1763877527835
fix-rpm
v3.0-DS_crash
add-claude-github-actions-1763663272333
add-claude-github-actions-1763663091346
add-claude-github-actions-1763663091411
add-claude-github-actions-1763476725261
add-claude-github-actions-1763476725489
v3.0_optimizations_and_stability
v2.7.3.1
v3.0.3-upgrade_json
v3.0.sonar-cli
v3.0.sonar-config
otel-tracepoint
v3.0.2-merge-upgrade_deps-add_new_distros
v3.0.2-upgrade_deps
v3.0.2-add_new_distros
v3.0-add_more_testing_groups
v3.0-upgrade_prometheus-cpp
v3.0-upgrade_json
v3.0-upgrade_sqlite3
v3.0-upgrade_libmicrohttpd
v3.0-upgrade_curl
v3.0-add_centos10_builds
v3.0-add_fedora42_builds
v3.0_PG_PrepStmt
v3.0-sliced_groups
v3.0_auth_negotiation
v2.7
v2.7-fix_run_name
v3.0_4799_4827
v3.0-3687
v2.7-pmm_runtime_servers_metrics
v2.7-4839
v2.7-4841
v2.7-bump_version_to_2.7.3
2.6.6-4841
v2.x_pg_PrepStmtBase_240714
v3.0-4803-4817
v3.0-4803
v2.7-minorBugs
v3.0-privates
v2.x-logging_mem_2
v2.7_fix
v2.7_amd64_build_fix
v2.7-fix_aux_threads_ssl_leaks
v2.7-fix_ssl_params_leak
v2.7-rm_malloc_conf_on_version
v2.7_compression
v2.7-actions-add-3p-tests-parameter
none
v2.7-fix_hang_on_resume
v2.x-logging_mem
v2.7_servers_defaults
v2.7-mariadb_column_metadata_integrity_check
ssl_optimization
v2.7_reg_test_4716_single_semicolon
v2.7_issue_4707_threshold_resultset_size
v2.7_reg_test_4723_query_cache_stores_empty_result
2.7_randomized_cache_ttl
v3.0_fix_multiple_builds
v3.0_servers_defaults
v2.7-update_actions_triggers_v2
v2.7-update_actions_triggers
v2.6
v2.6.x-update_triggers
v2.6-4646
v2.7.1-update_actions
v2.x
v2.6.x-testing-global-multiplexing-disabled
use-wrlock-in-dns-cache-empty
v2.6.x-fix-darwin
v2.x-admin_list_ciphers
v2.x-sqlite3_pass_exts
v2.x-tap_tests_opt_ssl
v2.6.0-update_to_libhttpserver_v0.19
v2.x_router_2ports
v2.6.0-update_to_openssl_v3.1.5
v2.x-2411025
v2.x-profiling_poc1
v2.x_sha2pass_draft2
v2.x-webui_fixes
v2.6.0-more-makefile-fixes
v2.x-20230914_test
v2.x-20230913_test
v2.5.5-branch
v2.5.5-branch_255_patches
v2.x-aurora_autodiscovery-refactor_cluster_mysql_servers-gr_bootstrap_mode_2
v2.x_mysql_connector_j_fixes
v2.6-deprecate_old_clickhouse
v2.x_refactor_cluster_mysql_servers
v2.x-aurora_autodiscovery
v2.x-zd70545
v2.x-aurora_autodiscovery_shunned_promotion
v2.x-tap20230609
v2.x-test20230530
v2.x_sha2pass_draft2-TEST
v2.x-session_track_system_variables_v2
v2.x-status-variables-for-set-stmts
v2.x-enable_session_state_trackers
v2.x-increase-logging-eof_fast_forward-t
v2.x-3863-special-query
v2.x-session_track_system_variables
v2.x_refactor_read_only_action
v2.x_sha2pass_draft1
v2.2.0-sqliteserver_read_only
v2.x-digest_umap_aux-comparison
v2.4.8
v2.x-4105_4114
v2.x-3583-server_closed_conn
v2.x-group_replication_rework-SHUNNED_promotion
v2.1.0-var-global-multiplex
v2.x-CI-hostname-tap-test-fixes
v2.x-limit-version-check
v2.x-fix_deprecate_eof_warning
v2.x-3698
v2.x_tidb_replica_read
v2.x-HostGroups_attributes
v2.0.18.221009
v2.x-ci_reg_test_3273_ssl_con
TAP_test_restapi
v2.x-tap_tests_groups
v2.x-tap_test_sqlite3_server-t
PRS_3888_3903_2
PRS_3888_3903
v2.x_code_refactor_2206
v2.x-multipacket_poc_1
v2.x-impr_hg_latency_obsv
v2.x-gcc-warnings
v2.x-hg_lock_session_id
v2.x-3768
v2.x-3371
v2.x-ci_verifications
v2.x-thread_local_qps_limit
v2.x-parser_table
v2.1.1-3207
v2.x-qps_limits
v2.x-3711
v2.x-3642
v2.x-3674
v2.x-ssl3_warnings
V2
v2.3.2
v2.3.2_3646_3647
v2.x-client_err_limit_conn_timeout
v2.x-keep_multiplexing_regression_fix
v2.3.2-3628
v2.2.2-to-v2.3.0-7
v2.2.2-to-v2.3.0-7_merge
v2.2.2-to-v2.3.0-6
v2.2.2-to-v2.3.0-6_merge
v2.2.2-to-v2.3.0-5
v2.2.2-to-v2.3.0-4
v2.2.2-to-v2.3.0-3
v2.2.2-to-v2.3.0-2
v2.2.2-to-v2.3.0-1
v2.3.1
v2.0.14-70226
v2.3.0
v2.x-client_err_limit-gr_replication_lag_action
v2.2.2
v2.2.1-3603
v2.2.1-centos7-ASAN
v2.2.1
v2.2.1-3601
v2.2.1-3599
v2.2.1-3597
v2.2.1-3595
v2.2.0-restapi_server_exc_log
v2.x-3574
v2.x-3558
v2.2.0-3546-centos-7-gcc-8
v2.x-3549
v2.x-cluster_large_mysql_users
v2.x-cov_ci_verification
v2.0.14-tb1
v2.0.14-tb1-3494
v2.0.14-tb1-3488
v2.0.14-tb1-3117
v2.0.14-tb1-2762
v2.0.14-2762
v1.4.13-arm
v2.1.1-3296
v2.2.0
v2.0.18
v2.1.1
v2.0.18-3342
v2.0.18-3182
v2.1.1-3184
v2.1.0-revert-da7fdfe14
v2.0.18-revert-da7fdfe14
v1.4.13-70160
v2.0.18-3354
v2.0.18-3350
v2.0.14-3339
1.4.13-70160
v2.0.18-3339
v2.1.1-3317
v2.1.1-3319
v2.0.18-3317
v2.1.2-LBalgo
v2.0.18-1574
v2.1.2-hgman
v2.0.17
v2.1.0
v2.0.17-3288
v2.0.17-3276
v2.0.17-3273
v2.0.16
v2.0.16-3267
v2.0.16-3265
v2.0.16-3262
v2.0.16-3261
v2.1.1-3252
v2.1.1-collation
v2.0.16-3252
v2.0.16-collation
v2.1.0-parser
v2.0.16-3219
v2.0.16-3216
v2.0.16-3201
v2.0.16-2330
revert-3191-v2.0.16-3190
v2.0.16-3204
v2.0.16-3177
v2.0.16-2619
v2.0.16-3190
v2.0.16-3187
v2.1.0-70118
v2.0.16-3133
v2.0.16-3133_ci_verification
v2.0.16-3150
v2.0.16-change_user
v2.0.15
v2.0.15_amd64_fix
v2.0.15_arm64_packages
v1.4.14-ssl
v2.0.15_arm64
v2.1.0-2820
v2.0.15-sslbug
v2.0.15-KillTrx
v2.0.14
v2.0.14-ch_build_fix
v2.0.14-focal
v2.0.14-valgrind20200904
v2.1.0-3042
v2.0.14-3035
v2.0.14-3036
v2.0.14-2955
v2.0.14-vars
v2.0.14-3005
v2.0.14-3003
v2.0.14_2970_2979
v2.0.14-NOTSOCK
v2.1.0'
v2.0.14-2958
v1.4.10-zd
v2.0.13
v2.0.13-autocommit_fix
v2.1.0-2892
v2.0.13-2711
v2.0.13-duplicated_variables
v2.0.13-duplicated_variables_for_2.1.0
v2.0.12-deprecate_eof
v2.1.0-1377
v2.1.0-admin_queries
v2.0.12-var-global-multiplex
v2.1.0-var-foreign-key
v2.0.12
v2.0.12-tab-small-log
v2.0.12-var-foreign-key
v2.0.12-var-long-query-time
v2.0.12-galera-shunned
v2.1.0-admin_queries_2
v2.1.0-tap-rm-config
v2.0.12-tap-rm-config-test
v2.1.0-QP_stmt_3
v2.0.11-fix-multi-2-ci
v2.0.11-fix-multi
v2.0.11-266_0-3
2.1.0
v2.0.11
v2.1.0-track-vars
v2.1.0-track-variables
v2.0.11-track-variables
v2.0.11-2526
v2.0.11-tap-tests
v2.0.13-2698-commit1
v2.0.10-galera-pxc-maint-mode
v2.0.11-track-vars
v2.0.10-2647
v2.0.11-track
v2.0.11-track-session-vars
v2.0.9-var-array-review
v2.0.11-stats
v2.0.10
v2.0.10-centos67
v1.4.14.2
1.4.14.2
v1.4.14-show-warnings
v2.0.9
v2.0.9-var-array_2
v2.0.9-var-array
v1.4.16
v2.0.8
val214-changing_charset
v2.0.6
v1.4.16-1922_2
v1.4.13.2
v2.0.4-charset248
v2.0.5
v1.4.10-67841
v2.0.4
v2.0.4-sqlite327
v2.0.3
v2.0.2
v1.4.15
v2.0.1
v1.4.14
v2.0.0
v1.4.14-ping_shun
v1.4.14-1828
v1.4.14-latency_awareness
v1.4.12
v1.4.13-admin_deadlock
v2.0.0-improve_speed
v1.4.13
v1.4.13-autocommit_revert
v1.4.11.2
v1.4.13-ps
v2.0.0_bionic_deb_fix
v2_962
v1.4.12-1640
v1.4.11-names_tz
v1.4.12-1693
master
v1.4.11
v1.4.10
v1.4.6
v1.3.10
jenkins_test
v2.0.0-cachegrind
v1.4.9
v2.0-lab
v149_1511
v149_1382
v1.4.7-f2
v1.4.7-f1
v149_1491
v1.4.5-kub
v1.4.8
v2.0-web2
v1.4.3
v1.4.7
bsd_install_update
v1.4.2
v1.4.1-ch2
v1.4.1
v1.3.9
v1.4.1-ch
v1.3.8
v1.3.8-dev
v1.3.7
v1.3.7-dev
v1.3.6-dev
v1.4.0-clickhouse
v1.4.0
v1.3.6
v1.3.5
v1.3.5-dev
v1.4.0-955
v1.3.4
v1.3.4-dev
v1.3.3
v1.3.3-dev
v1.3.2
v1.3.2-dev
v1.3.2-766
v1.3.0h
v1.3.1-utf8mb4
1.4.0-840
v1.3.1
v1.2.6
v1.3.0
v1.4.0-797
v1.2.5-715
v1.2.5
v1.2.4-lowmem
v1.3.1-dev-mem
v1.2.0
connleak
lab-1.2.0
v1.1.2
T107_add_proxysql_consul_requirements
T89_write_consul_integration_doc
T98_consul_multi_table_config
mongoose
evhttp
SQLiteServer
1.0
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
2.7.3
2.6.6.1
3.0.1
2.7.2
3.0.0
2.6.6
2.7.1
2.7.0
2.6.5
2.6.4
2.6.3
2.6.2
2.6.1
2.5.5
2.6.0
2.5.4
2.5.3
2.5.2
2.5.1
2.4.8
2.5.0
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
2.4.1
2.4.0
2.3.2
2.3.1
2.3.0
2.2.2
2.2.1
2.2.0
2.0.18
2.1.1
2.0.17
2.0.16
2.0.15
2.0.14
2.0.13
2.0.12
2.0.11
2.1.0
2.0.10
2.0.9
2.0.8
2.0.7
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
1.4.16
1.4.15
2.0.1
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.3.10
1.4.9
2.0.0
1.4.8
1.4.7
1.4.6
1.4.4
1.4.3
1.4.2
1.3.9
1.3.8
1.4.1
1.3.7
1.4.0
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0h
1.3.0g
1.3.0f
1.3.0e
1.3.0d
1.3.0c
v1.3.0b
1.4.5
v1.1.0
v1.1.0-rc
v1.1.1-beta
v1.1.1-beta.1
v1.1.1-beta.2
v1.1.1-beta.3
v1.1.1-beta.4
v1.1.1-beta.5
v1.1.1-beta.6
v1.1.2
v1.2.0a
v1.2.0b
v1.2.0c
v1.2.0d
v1.2.0e
v1.2.0f
v1.2.0g
v1.2.0h
v1.2.0i
v1.2.0j
v1.2.0k
v1.2.1
v1.2.2
v1.2.3
v1.2.4
v1.2.4.0923
v1.2.5
v1.2.6
v1.3.0
v1.3.0a
v1.3.0g
v1.3.0h
v1.3.1
v1.3.10
v1.3.2
v1.3.2-1
v1.3.3
v1.3.4
v1.3.5
v1.3.6
v1.3.7
v1.3.8
v1.3.9
v1.3.9-prev.1
v1.4.0
v1.4.1
v1.4.10
v1.4.11
v1.4.12
v1.4.13
v1.4.14
v1.4.15
v1.4.16
v1.4.2
v1.4.3
v1.4.4
v1.4.5
v1.4.6
v1.4.7
v1.4.8
v1.4.9
v2.0.0-beta.1
v2.0.0-rc1
v2.0.0-rc2
v2.0.1
v2.0.10
v2.0.11
v2.0.12
v2.0.13
v2.0.14
v2.0.15
v2.0.16
v2.0.17
v2.0.18
v2.0.2
v2.0.3
v2.0.4
v2.0.5
v2.0.6
v2.0.7
v2.0.8
v2.0.9
v2.1.0
v2.1.1
v2.2.0
v2.2.1
v2.2.2
v2.3.0
v2.3.1
v2.3.2
v2.4.0
v2.4.1
v2.4.2
v2.4.3
v2.4.4
v2.4.5
v2.4.6
v2.4.7
v2.4.8
v2.5.0
v2.5.1
v2.5.2
v2.5.3
v2.5.4
v2.5.5
v2.6.0
v2.6.1
v2.6.2
v2.6.3
v2.6.4
v2.6.5
v2.6.6
v2.7.0
v2.7.1
v2.7.2
v2.7.3
v3.0.0-alpha
v3.0.1
v3.0.2
v3.0.3
v3.0.4
v3.0.5
v3.0.6
v3.0.7
v3.0.8
v3.0.9
v3.1.6
v3.1.7
v3.1.8
v3.1.9
v4.0.6
v4.0.7
v4.0.8
${ item.name }
${ noResults }
5406 Commits (fix/pgsql-unix-socket)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
49371fd647 |
pgsql: omit port= when port==0 (Unix socket support)
Closes #5837. When pgsql_servers.port is 0 the hostname is documented to be a Unix-domain socket path. libpq rejects 'port=0' with 'invalid port number: "0"', so the field has to be omitted from the conninfo string. Add an 'if (port != 0)' guard at the three call sites that build libpq conninfo (client connect, backend kill, monitor) instead of creating a new helper header for a 3-line check. Add a regression TAP test (pgsql-socket-g1) that configures a pgsql_servers row with hostname='/var/run/postgresql-shared' and port=0, then exercises both the client connect path and the pgsql monitor. The infra uses a host-directory bind mount shared between the pgdb1 container (which creates the socket) and the ProxySQL container (which reads it), following the same pattern already used for the SSL cert directory in the same infra. |
3 weeks ago |
|
|
eed52db897
|
Merge branch 'v3.0' into v3.0_partition-fairness
|
1 month ago |
|
|
6909011b67 |
perf(partition): promote longest-waiting B session via max_connect_time fold
Under sustained contention ProcessAllSessions_Partition leaves the B (CONNECTING_SERVER) band unordered, so the pass can serve newer waiters ahead of older ones until they hit connect_timeout_server_max and abort. Track the oldest waiter during the classifier's is_B arm (no second pass) and swap it to running_end. Key on max_connect_time, which the is_B test already loads -- the min-compare is a register compare with no extra memory access, and the smallest value is the waiter closest to the timeout abort. Gated by |B| > PARTITION_FAIRNESS_MIN_B (=4) and partition_active. |
1 month ago |
|
|
a5bb7f640f
|
Merge branch 'v3.0' into v3.0_partition-gate
|
1 month ago |
|
|
46ab989adb
|
Merge commit from fork
fix(security): reject addresses after PROXY UNKNOWN (CVE-2026-48772 / GHSA-gw94-85m2-x8v2) |
1 month ago |
|
|
7dbe1f7029
|
Merge commit from fork
fix(security): bound first-packet recv() in data streams (CVE-2026-48773 / GHSA-58ww-865x-grpr) |
1 month ago |
|
|
3e7b77456e
|
Merge branch 'v3.0' into v3.0_partition-gate
|
1 month ago |
|
|
8025acdf60
|
Merge branch 'v3.0' into v3.0_pgsql_options_5801
|
1 month ago |
|
|
cda58357b2
|
Merge branch 'v3.0' into feature/ci-codecov-unit-tests
|
1 month ago |
|
|
b04caafef1 |
fix(coverage): unbreak lcov capture for {MySQL,PgSQL}_Session.cpp
Both lib/PgSQL_Session.cpp and lib/MySQL_Session.cpp contain a doxygen @note that *literally spells out* the strings `LCOV_EXCL_START` and `LCOV_EXCL_STOP` while documenting why those directives wrap the `assert(0)` block below the comment. lcov's geninfo scans every source line (comments included) for those tokens and treats them as real directives -- so the doc occurrence opens an exclude block, the real opener on the next assert opens it again, and geninfo aborts with: ERROR: <file>: overlapping exclude directives. Found LCOV_EXCL_START at line N - but no matching LCOV_EXCL_STOP for LCOV_EXCL_START at line M That error short-circuits the LCOV capture path in `test/infra/control/run-unit-tests-asan-coverage.bash` so `coverage/lcov.info` is never produced. The downstream "Upload coverage LCOV file" workflow step has been silently warning "No files found" for at least three runs (compare artifact listings of the three most recent CI-unit-tests-asan-coverage successes -- all zero artifacts), which in turn means the new Codecov upload step in #5817 also had nothing to send. Fix: rewrite the @note paragraph in both files so it describes what the directives do without literally containing the token strings, and explicitly call out that this is intentional. The wrapper directives around the actual `assert(0)` are unchanged. A clean lcov capture validates with `make ubuntu24-tap` followed by `docker compose run --rm --entrypoint bash ubuntu24_dbg_build -lc \ 'cd /opt/proxysql && test/infra/control/run-unit-tests-asan-coverage.bash'` which should produce a non-empty `coverage/lcov.info`. |
1 month ago |
|
|
e491c899ad |
refactor(pgsql): address PR review on #5801 options handling
- append untracked options in place to avoid temporary strings - bail out in the regression test when setup/introspection queries fail |
1 month ago |
|
|
093131cf27
|
Merge branch 'v3.0' into v3.0_pgsql_options_5801
|
1 month ago |
|
|
4bb067bf59 |
fix(pgsql): accumulate multiple untracked options startup parameters
The handler overwrote untracked_option_parameters on each iteration, forwarding only the last unrecognized parameter to the backend. Append them instead so all are preserved. |
1 month ago |
|
|
5e7677cb4d |
fix(pgsql): strip trailing space from backend options startup parameter
PgBouncer rejects an options value ending in whitespace; PostgreSQL tolerates it. Join tokens with a leading separator so it never does. Fixes #5801 |
1 month ago |
|
|
35cad4b4f4
|
Merge branch 'v3.0' into fix/kill-proxysqlgenai-build-flag-v2
|
1 month ago |
|
|
10c2c237e9 |
chore(sonar): use snprintf for DNS-counter row formatting
SonarCloud Quality Gate on PR #5809 is still ERROR despite all 0 TO_REVIEW hotspots being cleared (NOSONAR commits |
1 month ago |
|
|
de37c64f5e |
chore(sonar): tighten NOSONAR placement for remaining hotspots
Two SonarCloud hotspots from the previous round didn't actually pick
up the inline annotations:
- lib/DNS_Cache.cpp: the NOSONAR comment was on the line above the
`std::mt19937 gen(...)` construction. Sonar attributes the hotspot
to the construction line itself, so the comment needs to be inline
on that line. Moved it. Kept the explanatory comment block above.
- test/tap/tests/setparser_parsersql_test.cpp: new hotspot on the
strlen() call in the inline_validate_search_path helper added in
commit
|
1 month ago |
|
|
a315ebe0be |
fix(set-walker #150): document algo-3-vs-algo-0/1/2 whitespace divergence
#150 in pgsql-set_parameter_validation_test-t (`SET search_path = '"$user" , public'`) sees algorithm-dependent SHOW output because of an existing destructive behaviour in the regex SET parser path: PgSQL_Set_Stmt_Parser::set_query() runs remove_spaces() on the whole SET query, which collapses every whitespace run -- INCLUDING runs inside string literals -- to a single space before parsing. So under algorithms 0/1/2, PG receives `'"$user" , public'` and SHOW returns `"""$user"" , public"`. Under algorithm 3 (ParserSQL walker) the query is parsed as-is, the original `'"$user" , public'` reaches PG, and SHOW returns `"""$user"" , public"`. Algo 3 is the more correct behaviour (PG would never see the destructive collapse) but diverges from algorithms 0/1/2's historical behaviour. Earlier this session I considered making the walker call remove_spaces() too just to bring algo 3 in line. That would have papered over the issue by propagating the pre-existing data-mangling bug into the new code path. Better: - Leave the walker honest -- it stays the more correct path. - Document the algo-0/1/2 quirk inline in PgSQL_Session.cpp at the parser-selection site so future readers know why the two paths don't match byte-for-byte. - Teach the test about the divergence: SetCommandTest gains an optional `expected_value_algo3` field, populated only for the affected case (#150). At test startup we query `pgsql-set_parser_algorithm` from proxysql admin once and pick the appropriate expected value per case. A real fix would be to make remove_spaces() string-literal-aware (or stop running it on SET commands altogether). That's a larger change with risk to other tests calibrated against today's behaviour, so it's deferred to its own ticket; this commit keeps the regression green on both algorithm groups (PASS 1/345, FAIL 0/345 locally for both pgsql-set_parameter_validation_test-t under set_parser_algorithm_3-g1 and legacy-g6). |
1 month ago |
|
|
d7976aca13 |
fix(set-walker): PG walker gates on full-input AST coverage (not just status)
Pair-fix for the previous don't-lock change. ParserSQL returns
ParseResult::OK even when its AST only covers a prefix of the input
and silently drops the trailing junk -- for example
`SET search_path = public,,schema1` returns OK with an AST covering
`SET search_path = public`, and the `,,schema1` tail is lost. With the
new no-lock path that landed in
|
1 month ago |
|
|
35f84c384b |
fix(pgsql-session): don't lock hostgroup on parse fail for tracked vars
When the SET parser returns an empty map for a SET that targets a proxysql-tracked variable (search_path, datestyle, ...), the previous behaviour called unable_to_parse_set_statement(), which set *lock_hostgroup = true. From that point on, the entire SET-handling function was short-circuited for the rest of the session, so every subsequent SET -- including ones that DO parse and would have been caught by the per-variable validator -- bypassed proxysql entirely and went straight to PG. That cascade is what pgsql-set_parameter_validation_test-t case #184 hit: case #172's malformed `SET search_path = "unclosed_quote, public` caused the parser to (correctly) reject, locked the hostgroup, and from then on case #184's 64-char delimited identifier `SET search_path TO "1234...64chars..."` skipped the search_path validator's "> 63 chars -> reject" check and reached PG, which silently accepts/truncates such identifiers. The test then saw the SET succeed unexpectedly and reported the misleading "Value changed unexpectedly from '"$user"' to ''" message (test_ok flipped before the SHOW value was read; new_value defaults to "" in that branch). The fix: at this specific call site (inside the `match_regexes[1]->match(dig)` block, i.e. we already know the SET targets a tracked variable), drop the unable_to_parse_set_statement() call. Log a warning and return false so the SET is forwarded to PG normally. PG itself rejects truly malformed SETs (which was already the observed behaviour for cases #172-#183), and subsequent valid SETs on the same connection continue to flow through proxysql's validator. The locking branch at the outer `else` (when the regex didn't match -- i.e. genuinely unknown SET) is unchanged. End-to-end verification gates on CI -- there's no local PG infra in this build -- but the in-process unit test TestWalkerToValidatorChain184 (added in the previous commit) already confirmed that walker + validator together reject the 64-char input, which is exactly the path #184 now reaches with the lock removed. Diagnostic SET-VALIDATE proxy_info logging from the previous commit is removed. |
1 month ago |
|
|
950f6415b5 |
test+debug(set_param_validation #184): chain test + temp validator logging
Investigation of pgsql-set_parameter_validation_test-t case #184 (64-char delimited identifier > 63-char PG limit) has been blocked by divergence between static analysis and observed CI behaviour: - Static analysis: walker emits 66-char `"<64 digits>"` string, the search_path validator's quoted-branch counts effective_len=64, triggers `> 63` reject, returns false. Session error path generates an error packet to the client. SET should fail. - Observed in CI: no `[ERROR] invalid value for parameter "search_path"` log line at the time of case #184, despite the same log capturing every other validator-reject (client_encoding, DateStyle, IntervalStyle, etc.). Test reports `actual_success=true` (SET unexpectedly succeeded). The `"Value changed unexpectedly from '"$user"' to ''"` message is the test framework's artefact when test_ok flips before the value-comparison read. To pin where the disconnect actually is: * setparser_parsersql_test.cpp adds an inline copy of pgsql_variable_validate_search_path plus 3 strict cases plus a walker -> session-join -> validator chain test exercising the exact 64-char input. All 5 new assertions pass locally, confirming walker + validator are individually correct (the validator does reject 64 chars; walker does emit 66-char output). Chain test produces what production should be feeding the validator. * PgSQL_Session.cpp adds two `proxy_info` lines around the validator call in the SET-tracking block (pre and post). These will print value1 + validator return to the CI proxysql.log so we can see what proxysql actually feeds the validator for #184 and what it gets back. To be reverted once #184 is fixed. |
1 month ago |
|
|
6f63499731 |
chore(sonar): silence cpp:S2245 PRNG false-positives in DNS jitter sites
Two SonarCloud "weak-cryptography" hotspots flagged uses of mt19937 (DNS_Cache.cpp:117) and rand() (PgSQL_Monitor.cpp:2956). Both are non-cryptographic jitter sources -- one to spread the DNS cache TTL refresh, the other to spread the DNS bookkeeping refresh interval -- with no security boundary touching them. Adding inline NOSONAR annotations with the reasoning so future reviewers (human or bot) don't have to re-derive it. |
1 month ago |
|
|
0d39ac6991 |
build: kill PROXYSQLGENAI flag, PROXYSQL40=1 builds all plugins
PROXYSQLGENAI was a leftover from before the genai plugin carve-out. All genai/MCP/AI/RAG code now lives in plugins/genai/ as a runtime loadable .so. Since the plugin chassis (PROXYSQL40=1) already builds and loads the genai .so, a separate flag serves no purpose. Entrypoint changes (all three -- rhel, suse, deb): - Build: pass PROXYSQL40=1 (not PROXYSQLGENAI=1) to make. - Packaging: copy genai .so alongside mysqlx when PROXYSQL40=1. - protobuf-devel install: gate on PROXYSQL40=1 (needed for mysqlx). Automated packaging verification added to all entrypoints: rpm -qpl / dpkg -c confirms both .so files are in the package. ELF smoke test: validates .so is a valid shared object exporting proxysql_plugin_descriptor_v1 symbol. Fails build on mismatch. Test Makefiles: PROXYSQLGENAI -> PROXYSQL40 for the vec.o link gate (test/tap/tests/Makefile and test/deps/cluster_simulator/Makefile). Updated remaining PROXYSQLGENAI references to PROXYSQL40 in: CLAUDE.md, include/cpp.h, lib/proxy_sqlite3_symbols.cpp, src/main.cpp (3x comments), proxysql.spec, test/infra/control/start-proxysql-isolated.bash, test/infra/control/run-unit-tests-asan-coverage.bash, and 14 genai test file comments. |
1 month ago |
|
|
b54aaa5f76 |
fix(set-walker): preserve raw source for function calls and delimited idents
The ParserSQL-backed SET walker (algorithm 3) was round-tripping RHS values
through the Emitter, which normalises whitespace (adds ", " between function
call args) and drops delimiter quotes on identifiers (NODE_IDENTIFIER
emits its content without re-quoting). Both behaviours diverged from the
regex-based parsers used in algorithms 0-2.
The function-call drift cascaded across set_testing-t because the wrong
`sql_mode = concat(@@sql_mode, ',X')` value (with extra space) persisted on
the connection and tripped every subsequent variable comparison until reset.
The delimited-ident drift caused pgsql-set_parameter_validation_test-t to
treat `"MixedCase"` as `mixedcase` and `"$user"` as the current-user
substitution token (rather than the literal identifier the user wrote).
Walker fixes:
- NODE_FUNCTION_CALL -> paren-match in original query buffer from
value_ptr, return the verbatim substring.
- NODE_IDENTIFIER/NODE_COLUMN_REF with FLAG_IDENT_DELIMITED -> splice the
surrounding quote chars back in from value_ptr-1 / value_ptr+value_len.
Both helpers are no-ops when value_ptr is outside the query buffer (defensive
fallback to the existing emit_node_text path).
Tests: adds two strict (byte-exact) regression suites in
setparser_parsersql_test.cpp -- the existing normalize_value() collapses
whitespace and quote-style differences, which is what hid the bugs in the
first place. The new TestStrictFunctionCall and TestStrictPgsqlIdent
helpers compare verbatim so any future re-introduction is caught.
Local: 288/288 unit tests pass.
|
1 month ago |
|
|
1621ea2e2c |
fix(pgsql): preserve outer quotes on PG SET values in the walker
walk_set_stmt unconditionally called finalize_var_value (which calls strip_quotes) on every value, so `SET search_path TO '$user, public'` arrived at the session handler as `$user, public` -- outer single quotes already stripped. The handler then asked the validator to treat the whole thing as a comma-separated identifier list and the unquoted `$user` token was rejected with invalid value for parameter "search_path": "$user, public" For PostgreSQL, this breaks the PGTRACKED_VAR_OPT_NO_STRIP_VALUE contract: variables with that flag (currently only search_path) are supposed to retain their quoting because `"name"` vs `name` vs `'string'` are semantically distinct in PG. Variables that DO want stripping already route through PgSQL_Session.cpp's unquote_if_quoted() path, so their behavior is unchanged. MySQL still uses finalize_var_value -- single-value semantics, no need to preserve quotes through the walker. Fixes the 3 cases in test/tap/tests/pgsql-set_statement_test-t.cpp under set_parser_algorithm=3: SET search_path TO '\$user, public' (case 26) SET search_path TO 'public, \$user' (case 27) SET search_path TO 'public, \$user, pg_catalog' (case 28) These had silently passed before the CI infra fix in PR #5760 because the set_parser_algorithm_3-g1 pre-proxysql.sql hook was not being executed and proxysql ran with the default SET parser. |
1 month ago |
|
|
031f6fa1f5 |
fix(build): adapt callers of dns_cache counters to std::atomic
The previous commit promoted MySQL_Monitor::dns_cache_{queried,
lookup_success,record_updated} to std::atomic<unsigned long long>
but missed several call sites that pass them through implicit copy:
* lib/MySQL_Thread.cpp sprintf("%llu", GloMyMon->dns_cache_*) — varargs
cannot copy std::atomic.
* lib/PgSQL_Thread.cpp sprintf("%llu", GloPgMon->dns_cache_*) — same,
for the PgSQL counters.
* lib/MySQL_Monitor.cpp p_update_counter(..., GloMyMon->dns_cache_*) —
works via implicit operator T(), but explicit .load() is clearer
and matches the rest of the file.
Promote PgSQL_Monitor::dns_cache_* to std::atomic for the same race
that motivated the MySQL side (resolver workers increment, stats
readers and p_update_metrics read from another thread), and add
.load() at every read site so we don't depend on implicit conversion.
Verified with a local 'make -j32 debug' build in the integration
worktree.
|
1 month ago |
|
|
ca145d5026 |
fix(pgsql): atomic shutdown flag; honor dns_lookup fallback contract
GloPgMon->shutdown was a plain bool, written by main.cpp's teardown and read by the monitor / DNS resolver loops on worker threads — a data race that can let the loops spin past shutdown or observe a stale value indefinitely. Promote to std::atomic<bool> and switch the readers/writer to acquire/release ordering. PgSQL_Monitor::dns_lookup() was also returning an empty string when GloPgMon / dns_cache_thread weren't initialized yet, ignoring the return_hostname_if_lookup_fails contract. Move the fallback out of the dns_cache_thread branch so startup / shutdown behave like a normal cache miss for callers that asked for the hostname fallback. Addresses CodeRabbit review feedback on PR #5806. |
1 month ago |
|
|
039d538c2a |
fix(dns): correct inet_pton check; make DNS cache counters atomic
validate_ip() treated inet_pton(...) != 0 as success, but inet_pton returns 1 / 0 / -1; a -1 (e.g. unsupported family) would be reported as a valid IP. Compare against == 1 instead. The DNS cache counters (dns_cache_queried / dns_cache_lookup_success / dns_cache_record_updated) were declared as plain unsigned long long on MySQL_Monitor. Resolver workers update them atomically via __sync_fetch_and_add, but p_update_metrics() reads them from a different thread without a barrier, racing the writers. Promote to std::atomic<unsigned long long> and switch DNS_Cache to fetch_add / the atomic pointer type so both ends are consistent. Addresses CodeRabbit review feedback on PR #5806. |
1 month ago |
|
|
1d52499791
|
Merge pull request #5808 from sysown/issue_5639
fix(session): avoid double-free of stmt_meta pkt in LargePacket (#5639) |
1 month ago |
|
|
af4aa17346
|
Merge pull request #5807 from sysown/fix/5790-mariadb-collation-255
fix(core): validate_charset must replace collation 255 on MariaDB backends (#5790) |
1 month ago |
|
|
fadffdbcbd
|
Merge pull request #5806 from sysown/pgsql_dns_cache
Independent DNS cache for PgSQL (fixes #5768) |
1 month ago |
|
|
642b2327b7
|
Merge pull request #5805 from sysown/fix/parsersql-1.0.3-pg-set-fixes
fix: pgsql digest fixtures (typecast spacing) + ParserSQL 1.0.3 bump (PG SET TIME ZONE + multi-value lists) |
1 month ago |
|
|
3fd7aae059 |
fix(core): wrap MON_GALERA case body in braces (compile fix)
The previous commit introduced local variable declarations with
initializers (`const char *sv = …`, `bool is_mariadb = …`, etc.)
directly inside `case MON_GALERA:` of the `switch` in
`init_async()` at lib/MySQL_Monitor.cpp:742. The sibling
`case MON_CLOSE_CONNECTION:` / `MON_CONNECT:` / `MON_AWS_AURORA:`
labels then jump past these initializations, which GCC rejects:
MySQL_Monitor.cpp:779:14: error: jump to case label
MySQL_Monitor.cpp:781:14: error: jump to case label
MySQL_Monitor.cpp:783:14: error: jump to case label
Wrap the `#else` body of the MON_GALERA case in `{ ... }` so the
declarations live in their own scope and no sibling case can jump
over them. No behavior change.
The async path at lib/MySQL_Monitor.cpp:2299 was already inside its
own `{ ... }` block (added with the original code, not by this
patch), so it compiled fine and needs no change. The
`MySQL_Session.cpp` edits live inside `if / else if` chains with
their own braces, also unaffected.
|
1 month ago |
|
|
4eb52abf2c |
fix(pgsql,test): PG multi-value SET dispatch + test-fixture cleanup
Follow-up to the cluster-2 ParserSQL 1.0.3 bump (this same PR),
addressing review feedback from coderabbit + gemini.
## 1. PgSQL_Session: accept multi-value SET vectors (coderabbit, Major)
The previous commit `5a48004af` taught the adapter to walk every RHS
sibling so PG multi-value lists (e.g. `SET search_path TO "$user",
public`) come through as a `std::vector<std::string>` of every value.
But `lib/PgSQL_Session.cpp:4516` still had `size() > 2` →
`unable_to_parse_set_statement()`, which would have caused 3+ value
PG SETs to lock the hostgroup instead of being processed. Worse,
the downstream value-consumer at the same site used only
`it->second.front()`, silently dropping every value past the first
for valid 2-value SETs too.
Fix:
* Drop the upper bound from the cardinality check (keep `< 1` so
empty value lists still fail loudly).
* Join every value in the vector into `value1` with the
comma-separated form PG itself uses for these parameters
(`a, b, c`). Single-value SETs hit the loop with `size()==1` and
take just `it->second.front()`, preserving the previous behaviour.
The validator / hash-compare / tracker / param_status code below the
join is unchanged — it now receives the full joined value instead of
the truncated first element.
## 2. setparser_parsersql_test: drop INTERVAL test that locked in
incomplete behaviour (subagent correctness review, Major)
`parsersql_pgsql_time_zone` previously asserted that
`SET TIME ZONE INTERVAL '7' HOUR` produces `timezone = "INTERVAL"`,
which is the *current* observable output of ParserSQL — the
expression parser does not yet consume the `'7' HOUR` modifier
chain. Encoding that as expected output would flip the test red
when ParserSQL is later improved to capture the full interval
expression, conflating an improvement with a regression.
Removed the case; left a comment in the fixture explaining the gap
so a future contributor adds the case back together with the
ExpressionParser fix.
## 3. Diag-output cleanup (gemini, cosmetic)
* `%lu` → `%zu` for `size_t` (portability — `size_t` is not always
`unsigned long` on 32-bit / Windows).
* Extract the per-vector " | "-separated diag-string builder into
a single `join_values_for_diag()` helper used by both
`TestParse` (now also dumps full vector on mismatch, where it
previously printed just `vals[0]`) and `TestParsePgsql`.
## Verification
* `./setparser_parsersql_test`: 260/270 ok; the 10 remaining
not-ok are unchanged pre-existing failures (`sql_mode 23-25`,
`Set1_v2 0-1`), nothing new from this commit.
* `pgsql_time_zone` group: 6 assertions (3 cases × 2) — confirms
the INTERVAL case is removed cleanly.
* `pgsql_search_path` group: 16 assertions still all pass — the
multi-value join in PgSQL_Session does not affect the parser-
side test (which goes through the adapter, not the session).
|
1 month ago |
|
|
f2b53ea6e3 |
Address findings from independent diff review
A subagent code review on top of the CodeRabbit + Gemini bot reviews found five additional issues that the bots missed. All five are fixed here. 1. LOAD PGSQL SERVERS TO RUNTIME was waking MySQL's resolver, not PgSQL's. PgSQL_HostGroups_Manager::commit() inherited a MySQL_Monitor::trigger_dns_cache_update() call from a copy of the MySQL HGM, so after a LOAD pgsql hostnames had to wait for the refresh interval (default 60 s) before becoming resolvable — defeating the warm-cache-before-traffic intent that motivated issue #5768. Route to PgSQL_Monitor::trigger_dns_cache_update(). Verified directly: with refresh_interval=60000 ms, inserting a pgsql_servers row + LOAD now produces record_updated=1 within ~4 s instead of waiting a full minute. 2. DNSResolverWorker could deadlock shutdown. monitor_dns_resolver_thread isn't noexcept (vector growth, set_thread_name, etc. can throw); if it threw, the std::promise on DNS_Resolve_Data was never satisfied, the producer's future::get() blocked forever, the resolver loop never reached the shutdown check, and pthread_join in main hung. Wrap the call in try/catch and force-satisfy the promise with a failure result on any uncaught exit. 3. Test step 3 wasn't actually exercising the connect-path lookup it claimed. hammer_proxy() routes through the proxy front-end, which in standard test infra resolves through the default hostgroup — typically configured with an IP literal (see e.g. test/infra/docker-pgsql16-single/conf/proxysql/config.sql). IP literals bypass dns_lookup via validate_ip(), so the dns_cache_queried bumps observed came from the resolver loop alone, not from the connect path. Step 3 would have passed even if PgSQL_Connection::connect_start_DNS_lookup() was wired up wrong. Install a pgsql_query_rules row from inside the test that routes testuser to hostgroup 999, so the proxy actually calls into the cache on client connects. Clean up the rule in the test exit path. 4. Use-after-move in the _dns_cache_update debug log. Both PgSQL_Monitor::_dns_cache_update and MySQL_Monitor::_dns_cache_update logged debug_iplisttostring(ip_address) after std::move'ing ip_address into add_if_not_exist(). The moved-from vector is in a "valid but unspecified" state — typically empty — so the log printed "IP:[]" instead of the IPs. Capture the string before the move. Same bug also fixed in the bookkeeper expired-record requeue path inside PgSQL_Monitor::monitor_dns_cache. 5. monitor_dns_cache had inconsistent indentation inside the `if (hostnames.empty()) { ... } else { ... }` block introduced when I wrapped the original goto-based control flow. The braces were correct but the body sat at the wrong tab depth, making the scope visually misleading and prone to mis-edits. Re-indented. Findings deliberately skipped from the review (rationale in commit body): - "thread_local shared_ptr<DNS_Cache> keeps stale cache alive across GloPgMon recreate" — pre-existing MySQL pattern; GloPgMon is never destroyed mid-process today. - "PgSQL_monitor_dns_cache_pthread can deref GloPgMon during a tight shutdown" — shutdown ordering in main.cpp sets GloPgMon->shutdown before joining the thread and deletes GloPgMon only afterwards, matching the MySQL pattern. - "cache only seeded on ASYNC_CONNECT_SUCCESSFUL" — matches MySQL; pre-existing scope choice. - "validate_ip rejects bracketed IPv6" — pre-existing in MySQL; no current configuration path produces bracketed IPv6 in pgsql_servers. - "Test relies on outbound DNS for example.com" — matches the upstream MySQL test_dns_cache test which uses google.com / yahoo.com / amazon.com. Established convention. - "ai_family hard-coded to AF_UNSPEC for PgSQL" — already commented in code; follow-up if/when pgsql-resolution_family is added. |
1 month ago |
|
|
81bcc802da |
fix(core): apply MariaDB / MySQL 9.x detection to sibling version checks
The same mental defect fixed in lib/MySQL_Variables.cpp:validate_charset()
(commit before this one) exists at four other call sites in core. All
four use a first-character or 3-byte string-prefix comparison against
server_version and consequently misclassify either MariaDB or MySQL 9.x
(or both). Two are latent (MariaDB happens to land on the still-working
branch); the two in MySQL_Monitor.cpp are an active break on MySQL 9.x
Galera/PXC, because `INFORMATION_SCHEMA.GLOBAL_STATUS` was removed in
MySQL 8.4 and MySQL 9.x falls into the else branch that targets it.
Audited sites and fixes:
lib/MySQL_Session.cpp:2607-2615 -- tx_isolation / tx_read_only
Pre-fix: `strncmp(sv,"8",1)==0` chose `transaction_isolation` /
`transaction_read_only`; everything else got `tx_isolation` /
`tx_read_only`. MySQL 9.x fell to the else branch, but `tx_isolation`
was removed in MySQL 8.4; on MySQL 9.x the SET fails. MariaDB also
fell to the else branch -- coincidentally correct, since MariaDB
keeps `tx_isolation` across all versions.
Post-fix: use the modern name only for non-MariaDB MySQL >= 8.0
(any major), so MySQL 8.0/8.4/9.x all get `transaction_isolation`
and MariaDB 10/11 keeps `tx_isolation`.
lib/MySQL_Monitor.cpp:749 (sync MON_GALERA setup)
lib/MySQL_Monitor.cpp:2297 (async MON_GALERA dispatch)
Pre-fix: `strncmp(sv,"5.7",3)==0 || strncmp(sv,"8",1)==0` picked
performance_schema.global_status; everything else used
INFORMATION_SCHEMA.GLOBAL_STATUS. MySQL 9.x fell to the else branch
and queries INFORMATION_SCHEMA.GLOBAL_STATUS, which was removed in
MySQL 8.4 -- monitor query fails on MySQL 9.x Galera/PXC. MariaDB
Galera correctly fell to the else branch and uses
information_schema, which is where MariaDB keeps GLOBAL_STATUS.
Post-fix: use performance_schema for non-MariaDB MySQL >= 5.7 (so
MySQL 5.7, 8.0, 8.4, 9.x all share that path); MariaDB Galera and
legacy MySQL/PXC < 5.7 retain the information_schema path.
Pattern used at all sites (matching the existing fix in
validate_charset):
const char *sv = ...->mysql->server_version;
bool is_mariadb = (sv != NULL && strstr(sv, "MariaDB") != NULL);
int sv_major = (sv != NULL) ? atoi(sv) : 0;
No dedicated test added for the Monitor / SET TRANSACTION paths in this
commit: the Monitor change is exercised by any mariadb10-galera or
mysql{8,9}x-* CI group with Galera/PXC backends, and the
transaction_isolation change by SET-isolation-level coverage in
existing TAP groups. The validate_charset regression test added in
the prior commit on this branch still covers the original #5790 path.
|
1 month ago |
|
|
79414c10f1 |
fix(core): guard atoi(server_version) in validate_charset (#5790 review)
Address @gemini-code-assist review on PR #5807: the previous patch unconditionally evaluated `atoi(sv)` in the disjunction `(is_mariadb || atoi(sv) < 8)`. If `sv` was NULL, the short-circuit on `is_mariadb` (false) would still reach `atoi(NULL)`, which is undefined behavior per the C standard. In practice `myconn->mysql->server_version` is non-NULL by the time validate_charset() runs (CHANGING_CHARSET is only reachable after the backend handshake has populated server_version), so this is defensive, not a real crash path. Still essentially free, and keeps the guard consistent with the existing NULL check on `strstr(sv, "MariaDB")`. No behavior change for any reachable input. |
1 month ago |
|
|
a62d1b4e99 |
Address CodeRabbit + Gemini review feedback
Fixes for actionable findings on PR #5806: DNS_Cache.cpp / hpp: - lookup(): initialize *ip_count = 0 on the disabled-cache fast path so callers don't observe a stale count from a previous lookup (CodeRabbit). - add_if_not_exist(): only bump counter_record_updated_ when an insert actually happened, and return that signal to callers. Previously a no-op call inflated the cache-update stats (CodeRabbit). - get_connected_peer_ip_from_socket(): drop the malloc, switch to a stack sockaddr_storage, and only assign result on AF_INET / AF_INET6 with a successful inet_ntop. Previously, on an unknown address family, we'd copy the uninitialized ip_addr buffer into result (Gemini + CodeRabbit). - monitor_dns_resolver_thread(): cache_ttl is signed int and at the max configured TTL (7*24*3600*1000 ms) `1000 * cache_ttl` overflows before being added to monotonic_time(). Force the multiply into unsigned long long space with 1000ULL (Gemini). - DNS_Cache::IP_ADDR::counter is now mutable so get_next_ip() (const) can __sync_fetch_and_add it without a const_cast (Gemini). PgSQL_Monitor.cpp: - monitor_dns_cache(): refresh pgsql_thread___monitor_local_dns_* before the loop, not just on the first version-bump. Otherwise the resolver runs its first pass against zero-initialized TTL / refresh interval and starts in the wrong enabled/disabled state until a later config bump (CodeRabbit). test/tap/tests/pgsql-test_dns_cache-t.cpp: - Step 7 ("Cache disabled by refresh_interval=0") was inserting an IP literal (0.0.0.0), which bypasses DNS regardless of the cache state. Switched to a resolvable hostname (example.com) so a regression in the cache-disable path would actually move counters and fail the assertion. Added a third assertion on dns_cache_lookup_success for symmetry. Plan adjusted to 17. Deliberately skipped: - CR comment about mysql_thread___resolution_family change requiring a cache flush: pre-existing MySQL behavior, out of scope for this PR. - CR comment about pthread_attr_init / setstacksize return checks in main.cpp: matches the existing un-checked pattern in MySQL_Monitor::run(). No need to diverge here. - Gemini comment about persistent thread pool vs. per-iteration spawn: MySQL_Monitor::monitor_dns_cache() also recreates the resolver threads each loop iteration; the PgSQL variant follows the same pattern. - Gemini comment about 2048-byte stack size: Thread::start takes ss in KB (lib/thread.cpp:46 `pthread_attr_setstacksize(&attr, ss*1024)`), so 2048 here means 2 MB, matching the MySQL resolver pool. |
1 month ago |
|
|
c10b30523c |
Test: cover pgsql DNS cache + fix whitespace handling
Adds pgsql-test_dns_cache-t mirroring the existing MySQL test_dns_cache
test, exercising 16 scenarios:
* pgsql-monitor_local_dns_cache_* variables propagate to runtime
* IP literal does not touch the cache
* Resolvable hostname populates dns_cache_record_updated
* Client connect through the proxy increments dns_cache_queried and
dns_cache_lookup_success on a cache hit
* Hostname with leading/trailing whitespace is trimmed before
resolution
* Unresolvable hostname is queried but produces no record (cache miss
bumps dns_cache_queried only)
* Removing pgsql_servers rows drops the orphaned cache record
* Cache disabled via refresh_interval=0 flatlines all counters
* MySQL DNS cache counters do not move in response to pgsql-side
activity (independence between the two caches)
While writing the test, step 4 (whitespace trim) caught a real bug:
PgSQL_Monitor::monitor_dns_cache was inserting hostnames verbatim from
the SQLite3_result into the resolver queue, so ' example.org ' was
handed to getaddrinfo() unchanged and failed. MySQL_Monitor sidesteps
this by reading via SELECT trim(hostname) FROM monitor_internal.*; the
pgsql variant reads directly from pgsql_servers_to_monitor so it needs
to call trim() in C++. Fix: trim before validate_ip / insert into
the hostnames set. The lookup path already trimmed, so the bookkeeper
key now matches.
Registered the test in groups.json under legacy-g4 and the mysql-*
variant g4 groups, matching how the other pgsql-* tests are grouped.
|
1 month ago |
|
|
0cb8b6dfa5 |
Register pgsql-monitor_local_dns_* names with Admin
The names were defined in PgSQL_Thread::variables but sat inside a commented-out block in pgsql_thread_variables_names, so Admin's has_variable() returned false and SET pgsql-monitor_local_dns_* was rejected with "Unknown global variable". Move them out of the /* ... */ so the variables actually show up in global_variables and runtime_global_variables and can be tuned at runtime. Verified end-to-end on a smoke run: SET ... LOAD PGSQL VARIABLES TO RUNTIME succeeds, the resolver loop populates the cache, and a client connect through the proxy increments dns_cache_queried / dns_cache_lookup_success (cache hit, libpq skipped getaddrinfo). |
1 month ago |
|
|
a19894427e |
Add independent DNS cache for PgSQL
Fixes the watchdog asserts under DNS degradation reported in #5768. Symptom: with a PgSQL backend addressed by hostname, an unhealthy resolver made every PQconnectStart() block ~5s on getaddrinfo inside libpq. Under load, all PgSQL_Thread workers spent the bulk of each loop iteration in that synchronous DNS call, atomic_curtime fell behind the watchdog threshold (poll_timeout + 1s), and after restart_on_missing_heartbeats misses the watchdog asserts. MySQL avoids this because mysql-monitor's DNS cache lets MySQL_Connection::connect_start pass an IP directly to libmariadb; PgSQL had no equivalent. This change adds the equivalent for PgSQL, with state fully independent of the MySQL cache: * PgSQL_Monitor gains its own DNS_Cache, force_dns_cache_update flag, and dns_cache_{queried,lookup_success,record_updated} counters. PgSQL_Monitor::dns_lookup / update_dns_cache_from_pgsql_conn / trigger_dns_cache_update mirror the MySQL_Monitor surface. * A new background thread (PgSQL_monitor_dns_cache_pthread) drives PgSQL_Monitor::monitor_dns_cache(), which walks PgHGM->pgsql_servers_to_monitor and feeds the shared DNSResolverWorker pool. Launched alongside PgSQL_monitor_scheduler and lives independently of pgsql-monitor_enabled, matching MySQL. * PgSQL_Connection::connect_start now consults the cache. On a hit it appends `hostaddr=<ip>` to the libpq conninfo while keeping `host=<hostname>`; libpq documents this combo specifically to skip name resolution while preserving TLS hostname verification. On a miss / IP literal / disabled cache we fall back to the previous behavior (libpq does getaddrinfo). * Successful PgSQL connects seed the cache via update_dns_cache_from_pgsql_conn, so the second connect avoids getaddrinfo even before the resolver loop has visited the host. * The pgsql-monitor_local_dns_cache_ttl / _refresh_interval / _resolver_queue_maxsize variables (already accepted by Admin via PgSQL_Thread's variable registry) now actually propagate to pgsql_thread___monitor_local_dns_* globals. The propagation block in PgSQL_Thread::refresh_variables was previously commented out, so the values never reached anywhere. * The runtime stats output (SQL3_GlobalStatus) now exposes the PgSQL_Monitor_dns_cache_* counters alongside the existing PgSQL_Monitor_* counters. DNSResolverWorker is shared infrastructure added to DNS_Cache.hpp/cpp, used here by PgSQL_Monitor. MySQL_Monitor still uses its existing ConsumerThread-based pool; nothing about the MySQL cache changes. |
1 month ago |
|
|
a2fff3725f |
Extract DNS cache into shared DNS_Cache module
DNS_Cache, DNS_Cache_Record, DNS_Resolve_Data, the resolver worker, and
the validate_ip / get_connected_peer_ip_from_socket / debug_iplisttostring
helpers used to live inside MySQL_Monitor.{hpp,cpp}. Move them to a new
DNS_Cache.{hpp,cpp} so the same plumbing can back an independent
PgSQL_Monitor cache.
DNS_Cache no longer references GloMyMon directly; counters are wired in
per-instance via set_counters(). monitor_dns_resolver_thread no longer
reads mysql_thread___resolution_family; the desired ai_family is now a
field on DNS_Resolve_Data set by the caller. MySQL_Monitor wires both up
in its constructor and resolver loop respectively; behavior is identical.
No change to the MySQL DNS cache semantics.
|
1 month ago |
|
|
b3f7d29d51 |
fix(session): avoid double-free of stmt_meta pkt in LargePacket (#5639)
When handler_WCD_SS_MCQ_qpo_LargePacket() is reached via the COM_STMT_EXECUTE path, MySQL_Protocol::get_binds_from_pkt() has already aliased stmt_meta->pkt to pkt->ptr (see the FIXME at MySQL_Protocol.cpp:2873). The subsequent RequestEnd() -> Query_Info::end() free()s stmt_meta->pkt (the fix introduced for bug #796 at MySQL_Session.cpp:455), and then LargePacket's own l_free(pkt->size, pkt->ptr) frees the same buffer a second time. With jemalloc this silently corrupts the arena and surfaces later as the SIGSEGV reported in #5639, with the crashing frame landing on the l_free call site (+0x10e into LargePacket). Under ASAN the double-free aborts deterministically with a backtrace whose two free() chains match the report exactly. Fix: capture whether CurrentQuery.stmt_meta aliases pkt before calling RequestEnd() (which clears stmt_meta), and skip the second free when the alias was present. For the COM_QUERY path through LargePacket, stmt_meta is always NULL, so the previous behaviour is preserved there. Also add reg_test_5639_stmt_execute_max_allowed_packet-t which exercises the STMT_EXECUTE > mysql-max_allowed_packet path and asserts the session and process survive. |
1 month ago |
|
|
3ad60f6881 |
fix(security): hygiene follow-ups for PP1 UNKNOWN handling (GHSA-gw94-85m2-x8v2)
Four small fixes that came out of post-fix review of the original GHSA-gw94 commit: 1. lib/proxy_protocol_info.cpp — defensively clear `header_was_unknown` at the top of parseProxyProtocolHeader(). The default constructor zero-inits it, but callers may reuse a ProxyProtocolInfo across multiple parse attempts; a stale `true` from a prior UNKNOWN parse would cause the caller to take the UNKNOWN branch on a later malformed parse, suppressing the legitimate warning. 2. lib/mysql_data_stream.cpp — in the UNKNOWN branch of buffer2array, populate PROXY_info->proxy_address and proxy_port from the real TCP peer (mirroring the TCP4/TCP6 branch at lines 1290-1296). The PROXYSQL INTERNAL SESSION JSON output previously reported empty proxy_address / proxy_port=0 for UNKNOWN frames even though the real upstream LB peer was known. 3. lib/mysql_data_stream.cpp — emit header_was_unknown in the PROXY_V1 JSON block so audit/observability consumers can distinguish a spec-compliant UNKNOWN observation (with intentionally-empty source/destination address fields) from any other state where those fields happen to be empty. 4. include/proxy_protocol_info.h — document the dual-return contract above parseProxyProtocolHeader(): returning false with header_was_unknown=true means "valid UNKNOWN, caller must NOT override client_addr". This guards against a future maintainer flipping the return value to true and accidentally letting the caller's success-branch strdup an empty source_address into addr.addr. No regression-test changes were needed — the existing unit test already pins header_was_unknown=true on UNKNOWN, and the integration test pins client.client_addr.address (not proxy_address) which is the real security boundary. |
1 month ago |
|
|
d8e51349e2 |
fix(core): validate_charset must replace collation 255 on MariaDB backends (#5790)
Commit
|
1 month ago |
|
|
5a48004af5 |
fix(deps): bump ParserSQL to v1.0.3 — PG SET TIME ZONE alias + multi-value list
ParserSQL v1.0.2's PG SET parser had two bugs that were hidden in CI until PR #5760 fixed `test/infra/control/ensure-infras.bash` to actually dispatch `pre-proxysql.sql` hooks (previously only `.bash` hooks ran). With the harness fix in place, `set_parser_algorithm_3-g1` for the first time ran its tests under `pgsql-set_parser_algorithm=3`, surfacing: * `pgsql-set_parameter_validation_test-t` — `SET search_path TO "$user", public` parsed as `search_path = "$user"`, dropping every value after the first comma. * `pgsql-set_statement_test-t` — `SET TIME ZONE 'UTC'` parsed as `time = ZONE`, dropping the actual timezone value entirely. ## Upstream fix ParserSQL v1.0.3 (ProxySQL/ParserSQL PR #38) is the upstream parser fix: * PG `SET TIME ZONE <value>` is now recognised as the PG alias for `SET TimeZone = <value>`. The two-word keyword is detected via case-insensitive identifier lookahead since the tokenizer has no dedicated TK_TIME / TK_ZONE keyword. * PG `parse()` no longer shares MySQL's comma loop. In PG, the comma after the first value is value-list continuation — each subsequent expression is appended as another child of the same NODE_VAR_ASSIGNMENT node, alongside the first RHS. Full upstream test suite: 1223/1223 pass; 0 regressions. ## ProxySQL-side changes * `deps/parsersql/parsersql-1.0.3.tar.gz` — new tarball, replaces 1.0.2. * `deps/parsersql/parsersql` symlink retargeted to `parsersql-1.0.3`. * `lib/Query_Processor_ParserSQL.cpp::walk_set_stmt` — the PG multi-value fix means a single NODE_VAR_ASSIGNMENT can have multiple RHS siblings. The adapter now iterates `target->next_sibling` chain instead of reading a single sibling, so the `map<string, vector<string>>` for `SET search_path TO 'a', 'b', 'c'` carries `["a", "b", "c"]` rather than `["a"]`. Fully backward-compatible for MySQL (always one RHS). * `test/tap/tests/setparser_parsersql_test.cpp` — adds four permanent regression-test groups exercising the library + adapter end-to-end without a live backend: * `mysql_filtered_set` (7 cases) — verifies the filtered-SET variables parse cleanly so the downstream filter logic gets the input it expects. * `mysql_set_testing` (4 cases) — multi-variable comma-separated SET samples from `set_testing-240.csv`. * `pgsql_search_path` (8 cases) — single-value and multi-value shapes from `pgsql-set_parameter_validation_test-t`. * `pgsql_time_zone` (4 cases) — every `SET TIME ZONE ...` shape exercised by `pgsql-set_statement_test-t`. The 4 new assertions for the `INTERVAL '7' HOUR` case capture today's actual ParserSQL output (`timezone = [INTERVAL]`) — the expression parser does not yet consume the full interval modifier chain. The test reflects observable behaviour so it stays green; tightening to capture the full interval value is a future ExpressionParser improvement. ## Test plan - [x] Local rebuild of ProxySQL from the new 1.0.3 tarball: clean. - [x] `./setparser_parsersql_test`: 46 new assertions, all pass. - [x] No regressions in the 256 pre-existing assertions. The same 10 pre-existing failures (sql_mode 23-25, Set1_v2 0-1) — unrelated to this work, present before the upgrade. - [ ] CI on this branch: TAP groups `legacy-g2`, `mysql84-g2`, and `set_parser_algorithm_3-g1` are expected to flip green for the ParserSQL-related failures. Two non-ParserSQL bugs on the algorithm=3 ProxySQL session-dispatch path (`test_filtered_set_statements-t`, `set_testing-t`) remain to be investigated separately — the adapter now returns the correct maps, but downstream dispatch still misbehaves. ## Dependency Should not be merged before ProxySQL/ParserSQL PR #38 is merged and a v1.0.3 tag is cut. The vendored tarball in this commit was built from that PR's branch head; once the upstream tag exists the tarball SHA should be identical to a fresh `git archive --prefix=ParserSQL-1.0.3/ v1.0.3 | gzip` from the upstream tag. |
1 month ago |
|
|
1d2e080a66 |
fix(security): reject address fields in PROXY-Protocol v1 UNKNOWN frames (GHSA-gw94-85m2-x8v2)
The PP1 parser accepted "PROXY UNKNOWN <src> <dst> <sport> <dport>\r\n" as a well-formed header and let the parsed source address overwrite addr.addr, which is what Query_Processor reads for client_addr rule matching and what event_log / stats_mysql_processlist record. A peer that can reach the MySQL frontend (default mysql-proxy_protocol_networks = '*') could forge any source IP and bypass any client_addr-pinned ACL or routing rule. The HAProxy PROXY-protocol v1 spec is explicit: when the protocol token is UNKNOWN, the receiver MUST ignore any address fields that follow. Split UNKNOWN from TCP4/TCP6 in the parser: - For UNKNOWN, validate the byte after the token is ' ' or '\r' (rejects bogus tokens like "UNKNOWNFOO"), set a new header_was_unknown flag, and return false so the caller does not override addr.addr. - For TCP4/TCP6, require a single space delimiter after the 4-byte token before running sscanf. Previously a 4-byte memcmp accepted "TCP4xyz ..." as TCP4. Update mysql_data_stream.cpp to branch on header_was_unknown so it records the frame in PROXY_info without overriding addr.addr, and logs the skip at info level (not warning). PgSQL frontend is unaffected — only MySQL calls parseProxyProtocolHeader. |
1 month ago |
|
|
53eea80aaf |
feat(partition-gate): suppress low-volume ticks via min-attempts floor
Add PARTITION_GATE_MIN_ATTEMPTS (=4). When a tick has fewer pool acquires than this, leave both gate state and streak counter untouched. Filters the "2/2 NULL = 100% stressed" noise case without drifting the gate OFF on transient idle ticks (which would happen if low- volume ticks were treated as not-stressed). Pairs with the existing mysql_sessions->len > 3 guard at the partition call site. |
1 month ago |
|
|
878ba3b1e6 |
refactor(partition-gate): consolidate into Base_Thread; drain every iteration; widen ratio to uint64_t
Three closely related changes:
* Move the four partition_* members and note_pool_attempt() from
MySQL_Thread / PgSQL_Thread into Base_Thread. Eliminates 22 lines
of duplicated gate logic across the two protocol implementations.
* Run update_partition_gate() once per process_all_sessions outer
iteration, before the sess_sort / len > 3 / partition_active
check. Per-tick counters can no longer accumulate stale across
ticks where partition is skipped (sess_sort off, IDLE_THREADS
maintenance thread, or session count below threshold), which
in
|
1 month ago |
|
|
dcd143d39e |
revert: drop unrelated push_MyConn_local debug-leftover split
The two-line split of `MySrvC *mysrvc=(MySrvC *)c->parent;` into a
NULL-init plus assignment landed in
|
1 month ago |