mirror of https://github.com/sysown/proxysql
feature/ci-codecov-unit-tests
docs/passthrough-auth-spec
v3.0
v3.0_fix_pgsql-set_statement_test_5788
v3.0_pgsql_options_5801
fix/kill-proxysqlgenai-build-flag-v2
fix/kill-proxysqlgenai-build-flag
v3.0-260523
feat/passthrough-auth
GH-Actions
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
fix/5708-followup-multiline-for
fix/ci-asan-zombie-checks
v3.0_merge-5776-5784
genai_5534
aws-rds-bg
feature/perf-improvements-test2
v3.0_partition-gate
v3.0_fix-stale-pause-until
feature/perf-improvements-rene
v3.0_latency_consistency_improvement
fix/5796-ci-mysqlx-build-cache
fix/remove-skip-all
test/cluster-simulator
fix/galera-g5-cluster-start
integration/v3.0-batch-2026-05-13
fix/ghcr-pull-retry
fix/issue-5620-fast-routing-qr-leak
fix/issue-5684-tsdb-dashboard-same-origin
fix/5770-gcc16-jemalloc
fix/issue-5766-libconfig-escape-passthrough
v3.0_cap_violation_5767
fix/issue-5755-pgsql-digest-truncation
fix/issue-5580-deb-xz-compression
ci-mariadb10-galera-v3.0
ci-mariadb10-galera-GH-Actions
ci/fix-gr-g1-hostgroups
ci/fix-gr-g5-cluster-start
issue-5686-galera-vars
ci-mysql84-gr-g1-g9-GH-Actions
ci-mysql84-gr-g1-g9-v3.0
perf/pull-ci-base-from-ghcr
fix/rename-set-parser-group-and-bench-complexity
fix/split-test-groups
fix/rename-set-parser-workflow
perf/scram-cached-hmac
feature/parsersql-integration
gh-actions/add-set-parser-algorithm-3-g1
issue-5729-stats-projection-abi
fix/4760-lenenc-auth-v3.0
fix/tsan-unit-tests-build-failure
fix/4530-mysql-server-selection-prng
fix/4760-advertise-lenenc-auth-capability
fix/unit-test-asan-double-link
fix-auth-lock-order
v3.0-genai-plugin
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
ci-g5-debug-clean
feature/mysqlx-tls-passthrough
feature/mysqlx-asymmetric-tls
feature/mysqlx-state-machines
feature/build-tsan-plumbing
feature/mysqlx-observability-p0
plugin-chassis
fix/mysqlx-review-findings
fix/test-mysqlx-plugin-load-phase-b
docs/plugin-chassis-abi3-update
fix/mysqlx-runtime-views-separation
v3.0-ci-asan-libprotobuf-dev
ProtocolX
ProtocolX-rebased
v3.0-fix-macos-release-upload
v3.0-test-ci
v3.0-fix-init-release-race
v3.0-cleanup-stale-plans
v3.0-ci-pkg-workflows
fix/macos-build-deps
feat/arm64-on-demand-package-builds
fix/3.0.8-review-items
fix/pgsql-active-tx-on-broken-conn
feat/pgsql-tx-poisoned-recovery
pull-5659
session-track-system-variable
feat/cla-assistant-setup
v3.0-slim-dbdeployer-images
ci/fix-mysql-apt-key-expired-v2
ci/fix-mysql-apt-key-expired
fix/mysqlx-check-connect-poll
fix/mysqlx-stale-row-sync
feature/mysqlx-route-identity
fix/mysqlx-listener-lifecycle
fix/mysqlx-backend-tls-post-auth
chore/retire-dead-mysqlx-worker
v3.0-issue5621
v3.0_new_zstd
fix/lint-groups-json-format
v3.0-dbdeployer-mysql84-gr
lint-tap-tests-static-analysis
fix/groups-json-orphaned-entries
mariadb-rpl-helper
feature/gtid-range-update
fix-fc-parsing
v3.0-pgsql-monitor-reschedule-on-interval-change
v3.0-remove-sqlite-rembed
v3.0-fix-read-only-actions-hostgroup
v3.0-fix-pgsql-ssl-keylog-path
v3.0-fix-flake-test-flush-logs
v3.0-doc-test-readme
v3.0-doc-gh-actions-vocabulary
ci/fix-upload-artifact-eacces
v3.0_pgsql-copy-matcher-5568
ci/fix-cache-prune-permissions
ci/disable-unittests-caller
ci/shrink-test-cache
ci/proxysql-tester-zero-test-safety-net
ci/fix-tap-build-target
ci/gh-actions-readme-pointer
ci/rewire-group-callers-and-docs
ci/fix-mysql84-infradb-label
ci/add-missing-group-reusables
v3.0-lint
fix/ci-workflow-run-chain-pr-sha
fix/postgresql-cluster-sync_2
v3.0_ci_min_proxysql_version_5561
mysqlx-plugin-impl
infra-mysql57-binlog
v3.0-ci0405
feature/pgbouncer-compat
v3.0_pgsql_sslkeylog_5281
v3.0-issue5556
fix/5554-resolution-family-limitation
v3.0-CodeCov0325
v3.0-ci260323
fix/3p-ci-error-handling
feat/ffto-error-recording
v3.0-5493
v3.0-ci260322
v3.0-ci260322_cluster
v3.0-5516
v3.0-5517
copilot/feature-load-restapi-routes-config
copilot/add-ssl-tls-certificate-stats-table
unit-tests-skip-proxysql
private/multi-group-runner
v3.0-5473
v3.0-5499
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-mcp_rules_test
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.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.1.6
v3.1.7
v3.1.8
v4.0.6
v4.0.7
v4.0.8
${ noResults }
2537 Commits (6d8dff293973edd1be9cc67be03aac400e85cb4c)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
aa4a078988
|
Merge pull request #5700 from sysown/fix/test-mysqlx-plugin-load-phase-b
fix(test): test_mysqlx_plugin_load-t needs Phase B between load and init |
3 weeks ago |
|
|
7de1ae3dcd |
test(mysqlx): address PR-#5700 review feedback
Two reviewers flagged the same area in the previous commit (ec0c5...
oh wait wrong sha —
|
3 weeks ago |
|
|
eebfbde2b3 |
fix(test): test_mysqlx_plugin_load-t needs Phase B between load and init
Pre-existing test bug surfaced by CI-unit-tests-asan-coverage on
plugin-chassis (run 25202654334, head
|
3 weeks ago |
|
|
ef32d9df87 |
ci: register plugin_runtime_views_unit-t in groups.json
Lint failure surfaced on PR #5690's CI run (job 73893199128) — the chassis runtime-view test added in PR #5688 was never registered in test/tap/groups/groups.json, and check_groups.py treats any unlisted TAP source as a lint error. Same group entry as the sibling plugin-chassis tests (plugin_dispatch _unit-t, plugin_manager_unit-t, etc.): "plugin_runtime_views_unit-t" : [ "unit-tests-g1","@proxysql_min_version:4.0" ] unit-tests-g1 is the standard host-only TAP group (no docker backend required); the @proxysql_min_version:4.0 attribute keeps it from running against pre-chassis builds. Trivial fix that belongs on the same PR as the doc updates because the lint failure is what surfaces on every PR opened against plugin-chassis until this lands. |
3 weeks ago |
|
|
becbf09ffa |
fix(mysqlx): plugin_descriptor visibility + admin_tables test + dead decl
Three issues code-review caught.
# Plugin-descriptor visibility
plugins/mysqlx/Makefile builds the .so with -fvisibility=hidden. The
loader resolves proxysql_plugin_descriptor_v1 via dlsym(); without an
explicit visibility-default override on this single exported function,
the symbol stays hidden and ProxySQL_PluginManager::load() fails with
"undefined symbol: proxysql_plugin_descriptor_v1". Add the
__attribute__((visibility("default"))) override so the .so exports
exactly one symbol — the descriptor entry point — and no others.
Latent regression unblocked here (test_mysqlx_plugin_load-t was also
affected).
# test_mysqlx_admin_tables-t.cpp rewrite
This integration-style TAP test (registered as unit-tests-g1,
@proxysql_min_version:4.0) used to assert on runtime_mysqlx_<X>
contents after each LOAD/SAVE call:
mgr.dispatch_admin_command(ctx, "LOAD MYSQLX USERS TO RUNTIME", result);
ok(admin_db.return_one_int("SELECT COUNT(*) FROM runtime_mysqlx_users") == 1, ...);
Under the new architecture, LOAD updates MysqlxConfigStore and never
writes runtime_mysqlx_users. The runtime view is repopulated only via
the chassis pre-SELECT hook in ProxySQL_Admin::GenericRefreshStatistics
— a path the test bypasses by reaching admin_db directly. The test
also seeded only mysqlx_users without seeding runtime_mysql_users,
so the cross-module-join in install_users_from_admin would silently
drop every user. And the SAVE-after-modifying-runtime tests were
asserting on a no-op (SAVE no longer reads runtime_mysqlx_users).
Rewrite:
- LOAD assertions now go via rows_affected from the callback and
DELETE editable + SAVE roundtrip to confirm the in-memory store
really held the rows. If SAVE re-materialises the rows the
operator deleted from the editable table, they came from the
store — exactly the contract LOAD is meant to install.
- Cross-module canonical tables seeded explicitly: helper
seed_canonical_tables creates runtime_mysql_users +
runtime_mysql_servers via the canonical
ADMIN_SQLITE_RUNTIME_MYSQL_USERS / ADMIN_SQLITE_TABLE_RUNTIME
_MYSQL_SERVERS DDL.
- SAVE-after-runtime-mutation tests (lines 263+) rewritten:
instead of "modify runtime_mysqlx_users, then SAVE, expect change
in mysqlx_users", they affirmatively assert the new contract —
runtime-view edits do NOT propagate to mysqlx_users on SAVE.
- backend_auth_mode values normalised to canonical enum values
(service_account, pass_through, mapped) since
mysqlx_backend_auth_mode_from_string collapses unknowns to
`mapped` and would have hidden any round-trip bug otherwise.
45 / 0 asserts after rewrite.
# Dead declaration
MysqlxConfigStore::rebuild_hostgroup_endpoints_locked() declared in
the header but never defined or called. Drop it. Code review found
this in the same pass.
|
4 weeks ago |
|
|
90e888e1d0 |
fix(chassis): runtime-view dispatch fires unconditionally on admin
Doc-accuracy review found that proxysql_refresh_configured_plugin_
runtime_views was unreachable for plugin-registered tables. The call
was placed inside
if (refresh==true) { // ProxySQL_Admin.cpp:1637
...
if (admin) {
// existing core runtime_* refreshes
proxysql_refresh_configured_plugin_runtime_views(...)
}
}
`refresh` only gets set to true by hardcoded substring matches
against core's own table names (lines 1358-1634: runtime_mysql_users,
runtime_mysql_servers, runtime_mysql_query_rules, etc.). None of
those substrings match runtime_mysqlx_* (or any other plugin-
registered view), so on a bare
SELECT * FROM runtime_mysqlx_users
the gate was false, my dispatch was skipped, the table was empty
(or stale from a previous query that DID match a core substring),
and the SELECT returned wrong data. The whole "on-demand projection"
mechanism the previous commits documented was broken for the entry
case. Issue #5687 / PR #5688.
The fix is one-line structurally: hoist the dispatch out of the
`if (refresh==true)` block and place it right after the substring-
detection section, gated only on `if (admin)`. The chassis
dispatcher itself (refresh_runtime_views_for_query in
ProxySQL_PluginManager.cpp) already does its own per-view substring
match against query_no_space, so a query that touches no registered
view is a cheap no-op (one shared lock + N substring scans, N ==
registered-view count). Calling unconditionally on every admin
query is therefore both correct and cheap.
Test: new plugin_runtime_views_unit-t (20 ok asserts) drives
ProxySQL_PluginManager::register_runtime_view +
refresh_runtime_views_for_query directly. Covers:
- register_runtime_view rejects null callback / empty name /
case-insensitive duplicate.
- Per-query dispatch fan-out: only matching callbacks fire,
join queries fire all referenced views, unrelated queries
fire nothing, case-insensitive match works, backtick-quoted
identifiers match.
- Whole-identifier boundary: longer-suffix overlap (runtime_
mysqlx_users_extra), left-prefix overlap (stats_runtime_
mysqlx_users), embedded-in-string-literal — none falsely
match. Boundary cases (start of string, end of string) do
match.
This is the test the PR-#5688 review pass identified as the chassis-
hook coverage gap. Builds standalone (no fake-plugin loader needed)
since it drives the manager directly.
|
4 weeks ago |
|
|
b4127156ed |
fix(mysqlx): listener reconciler reads MysqlxConfigStore, not runtime view
Code-review finding on PR #5688. mysqlx_reconcile_listeners_impl in plugins/mysqlx/src/mysqlx_listener_reconcile.cpp was still issuing a SELECT against runtime_mysqlx_routes to build its desired route set: SELECT name, bind FROM runtime_mysqlx_routes WHERE active=1 After the previous commit decoupled module state from the runtime_mysqlx_<X> projection, that table is empty until an admin SELECT triggers the projection callback. The reconciler runs from two non-admin paths: - mysqlx_plugin.cpp::mysqlx_start() at process startup, after install_routes_from_admin populates the store - load_routes_to_runtime() admin command, after install_routes_from_admin populates the store Both paths fire BEFORE any admin SELECT has projected the runtime view, so the reconciler would see ZERO desired routes. Net effect in production: no mysqlx listeners bind on startup, and LOAD MYSQLX ROUTES TO RUNTIME silently removes any listeners that were already mapped (the reconciler treats every mapped route as "no longer desired"). The unit tests didn't catch this because the weak symbol mysqlx_reconcile_listeners is null in unit-test binaries (the listener-reconcile pure variant is the one tested, and previously it was reading a pre-populated SQLite table). # Fix Read the desired route set from MysqlxConfigStore directly via a new public method: std::vector<std::pair<std::string,std::string>> MysqlxConfigStore::snapshot_active_routes() const It returns a (name, bind) pair for every active route under a shared lock. The reconciler consumes the snapshot the same way the previous SQL-driven version consumed result rows. The pure variant signature changes from void mysqlx_reconcile_listeners_impl(SQLite3DB& admindb, ...) to void mysqlx_reconcile_listeners_impl(const MysqlxConfigStore&, ...) which both restores the function's "no global state" purity (it no longer needs to reach into mysqlx_context() and never has) and makes the data-flow obvious: the store is the input. The strong weak-symbol entry mysqlx_reconcile_listeners(SQLite3DB&) is unchanged externally — it still takes admindb (now ignored, kept for ABI stability) and grabs the store from mysqlx_context() internally. Doc comment on the weak hook in include/mysqlx_plugin.h updated to describe the new data flow and to spell out explicitly why we do NOT read runtime_mysqlx_routes. # Test updates The two robustness tests that exercise the reconciler (test_listener_reconciliation, test_listener_reconciliation_bind_ change) used to set up a SQLite admindb with runtime_mysqlx_routes rows. They now construct a MysqlxConfigStore directly and populate it via install_for_test() — a smaller, more honest fixture that matches what the reconciler actually consumes. Note: MysqlxConfigStore is non-copyable/non-movable, so the bind-change test installs into two stack-local stores back-to- back via a helper lambda rather than rebuilding by value. # Status - All 21 mysqlx unit tests still green (646 ok, 0 not_ok). - Listener reconciler now sees the right state in both startup and LOAD MYSQLX ROUTES TO RUNTIME paths. Closes the BLOCKER from the PR #5688 review. Other concerns the review surfaced were all dismissed as not-bugs (ABI 1/2/3 loader compat, sql_references_table_ci whole-identifier match, lock ordering, sqlite_quote correctness, save semantics matching the canonical pattern). |
4 weeks ago |
|
|
e5353ac922 |
test(mysqlx): update unit fixtures for module-owned runtime state
The four config-store / route-store unit tests, plus
mysqlx_admin_commands_unit-t, used to set up SQLite fixtures by
inserting directly into runtime_mysqlx_<X> tables and calling
MysqlxConfigStore::load_from_runtime(db, err). With the canonical
separation in the previous commit, install_*_from_admin reads the
editable mysqlx_<X> tables, so the fixtures had to move accordingly.
Mechanical changes:
CREATE TABLE runtime_mysqlx_<X> -> CREATE TABLE mysqlx_<X>
INSERT INTO runtime_mysqlx_<X> -> INSERT INTO mysqlx_<X>
store.load_from_runtime(db, err) -> store.install_all_from_admin(db, err)
+ add `comment` column to the editable DDLs (install_*_from_admin
SELECTs comment).
The cross-module dependencies (runtime_mysql_users,
runtime_mysql_servers) stay unchanged in the fixtures: those are
admin's projection of OTHER modules' runtime state, exactly what the
mysqlx install path SELECTs from.
Three semantic adjustments (not just renames):
- mysqlx_config_store_pure: a few tests previously asserted that a
canonical-only user (present in runtime_mysql_users, no row in
mysqlx_users) showed up in identities_. The new
install_users_from_admin drops those — a user with no x_enabled
flag has no path to authenticate via X anyway. Assertions adjusted
to reflect the dropped row.
- mysqlx_admin_commands: the LOAD callback rows_affected now reports
the active editable-table row count (was the runtime-table row
count); the SAVE VARIABLES callback always writes the four
canonical variables (was whatever happened to be in
runtime_mysqlx_variables). Assertions updated.
- mysqlx_admin_commands also adds explicit project_users_to_
runtime_view() calls before assertions that read runtime_mysqlx_
users contents — those assertions are exercising the projection,
so they need the projection to actually run, since outside admin
the chassis isn't there to fire it.
Result: 21 / 21 mysqlx unit tests green (646 ok asserts, 0 not_ok),
including 5/5 stable runs of mysqlx_concurrent_unit-t (the listener
O_NONBLOCK regression guard from earlier in this PR series).
|
4 weeks ago |
|
|
e68f72cf99 |
test(mysqlx): add diag logging + fix broken plan/schema in unit tests
Two related changes to all mysqlx_*_unit-t.cpp files.
# 1. Diagnostic logging across all 21 mysqlx unit tests
Before this commit none of the mysqlx unit tests emitted any output
beyond raw TAP `ok N`/`not ok N` lines. When CI-unit-tests-asan-
coverage hung mid-run on plugin-chassis (run 25021206900), the per-
test log file showed `ok 1 ... ok 6` and then nothing for ~110 minutes
until the workflow's 120-minute timeout killed the job. We could not
even tell *which* test was hung — the bash loop in the workflow only
logs `PASS:`/`FAIL:` after a binary exits.
Each binary now does:
- `setvbuf(stdout, nullptr, _IOLBF, 0)` as the first statement of
main(). Without this, when CI redirects stdout to a file the
default block-buffered mode swallows any output that hasn't filled
a 4KB-ish buffer — including diag lines emitted just before a
blocking syscall. Line-buffering means each `\n`-terminated diag
is flushed before the syscall, so a hang has 1-line-resolution
attribution in the log.
- `diag("=== <filename> starting ===")` right after `plan(...)`,
so the log always has at least one line proving the binary loaded
and reached main() (rules out crashes during static init).
- `diag(">>> %s", __func__)` at the top of every `static void
test_*()` subtest function called from main(), so a hang or
assertion failure points at the responsible subtest.
- In `mysqlx_concurrent_unit-t`, additional checkpoint diags inside
`test_concurrent_handshakes` ("starting Mysqlx_Thread", "spawning
N clients", "all clients spawned, joining", ..., "thr.stop()
returned") since the surrounding test was the one that actually
hung in CI; this gives a 7-checkpoint resolution within the body.
This change is the reason we were able to bisect the listener
O_NONBLOCK bug fixed in the previous commit: with these diags the
hang point ("all clients spawned, joining" → never reached "all
clients joined, sleeping 500ms") was visible in the per-test log
within seconds of running it.
# 2. Plan/fixture corrections in 4 tests that never actually passed
These tests were green in CI by virtue of nothing in the workflow
checking their exit codes (CI-mysqlx exercised a different path); the
moment CI-unit-tests-asan-coverage started actually running them they
came back red. Each was a real bug in the test harness, not in the
production code:
- mysqlx_backend_auth_unit-t.cpp: plan(42) but only 34 ok() can fire
on the success path. State_transitions emits 23, the remaining
six functions emit 11 — total 34. plan(42) was never reachable;
fixed to plan(34).
- mysqlx_session_unit-t.cpp: plan(62) but only 60 fire. Four `ok(
false, ...)` lines live in protobuf-parse failure branches that
the success path skips; fixed to plan(60).
- mysqlx_config_store_unit-t.cpp: load_from_runtime() SELECTs from
runtime_mysqlx_variables (the variables table the production code
uses to pick up thread_pool_size / connect_timeout / tls_mode /
max_cached_connections at runtime), but the test's fixture only
created 3 of the 4 mysqlx tables. Added kRuntimeMysqlxVariablesDdl
and the matching execute() — same shape the sibling
mysqlx_config_store_concurrent_unit-t already uses.
- mysqlx_route_store_unit-t.cpp: ad-hoc minimal DDL for
runtime_mysql_users / runtime_mysql_servers omitted columns the
production query SELECTs (password, weight). Switched to the
canonical ADMIN_SQLITE_RUNTIME_MYSQL_USERS and
ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_SERVERS macros and added the
runtime_mysqlx_variables table.
After this commit `for t in mysqlx_*_unit-t; do ./$t; done` is 21/21
green (754 ok asserts total, 0 not_ok, 0 timeouts), 10/10 stable across
repeated runs of the previously-flaky mysqlx_concurrent_unit-t.
|
4 weeks ago |
|
|
d4427731b7 |
Merge remote-tracking branch 'origin/v3.0' into plugin-chassis
Picks up the v3.0 fixes that unblock plugin-chassis CI: - |
4 weeks ago |
|
|
85ad4fe3b4 |
test(mysqlx): rewrite dispatch tests with real backend fixture (#5679)
Closes the last 5 cluster-3 failures from issue #5679. The 17 previously-skipped dispatch sub-asserts now run with proper coverage, plus 3 other pre-existing failures (#21 compression code, #29 TLS init, #43 forward-no-connection) are addressed. ## Background The dispatch tests asserted that one handler() call after writing a SQL/CRUD/PREPARE/CURSOR/EXPECT message left status_ exactly at CONNECTING_SERVER. That premise was wrong: forward_to_backend() sets to_process=true, and handler()'s `goto handler_again` loop immediately re-enters the switch, running handler_connecting_server() in the same call. After commit |
4 weeks ago |
|
|
99a745f6ed |
ci(mysqlx): wire mysqlx-soak group into TAP harness end-to-end
Completes the four follow-up items documented in the mysqlx-soak
group's README. After this commit, the harness scripts run inside
the proper docker-isolated TAP framework — no more ad-hoc invocations.
## (1) Add mysql-connector-python to proxysql-ci-base
test/infra/docker-base/Dockerfile installs python3 + a few pip
packages but lacked the X DevAPI bindings. Add
`mysql-connector-python` to the existing `pip3 install` line. Image
must be rebuilt (`docker build -t proxysql-ci-base:latest
test/infra/docker-base`); the new soak-tests CI job rebuilds
unconditionally per run, so CI gets the new package automatically.
## (2) TAP wrappers for the harness scripts
Two new Bash TAP entries under test/tap/tests/:
* test_mysqlx_soak_behavioral-t.sh — emits two TAP assertions:
scenario 1 = SIGTERM-mid-traffic (the harness signals the proxysql
container with `docker kill -s TERM proxysql.${INFRA_ID}` mid-run
and verifies clients receive Mysqlx::Error 1053 instead of TCP
RST); scenario 2 = LOAD MYSQLX ROUTES TO RUNTIME mid-traffic.
Both fall back to "skip" if mysql-connector-python is missing,
or if the proxysql container is unreachable after scenario 1.
* test_mysqlx_soak_stress-t.sh — single TAP assertion that wraps
stress.py. Defaults to 60s/20-clients to fit a CI timeout; long
soaks invoke stress.py directly with --duration 24h per issue
#5677.
Both wrappers default the connection params to the docker-internal
hostname `proxysql` (via network alias) so they work from inside the
test-runner container; environment overrides let local invocations
point elsewhere.
## (3) Register in groups.json
Two new entries:
"test_mysqlx_soak_behavioral-t" : [ "mysqlx-soak-g1", "@proxysql_min_version:4.0" ],
"test_mysqlx_soak_stress-t" : [ "mysqlx-soak-g1", "@proxysql_min_version:4.0" ],
Both use the @proxysql_min_version:4.0 tag (the harness only makes
sense in chassis-aware builds). Lint passes (421 entries, sorted).
## (4) CI job
Add `soak-tests` job to .github/workflows/CI-mysqlx.yml. Pattern
mirrors CI-taptests-pgsql-cluster.yml: restore build cache, build
plugin, build proxysql-ci-base, ensure-infras (TAP_GROUP=mysqlx-soak),
run-tests-isolated (TAP_GROUP=mysqlx-soak-g1), cleanup, archive logs
on failure.
The job runs after unit-tests passes (same dependency as e2e-tests)
and is independent of e2e-tests (parallel execution OK).
## What this covers
* Builds the plugin and rebuilds the test image with the X DevAPI.
* Stands up a real MySQL 8.4 backend (3-node replication via the
existing infra-dbdeployer-mysql84 image, X protocol on port
23306-23308 inside the docker network).
* Stands up ProxySQL in a container with the plugin .so bind-mounted
and a per-group config that declares plugins=("...").
* The mysqlx-soak setup-infras hook provisions one route, one user,
one endpoint, reloads, and verifies the listener bound on 6603.
* Two TAP tests run inside the test-runner container against the
freshly-stood-up ProxySQL, exercising the plugin end-to-end.
## What this does NOT cover
* Long-running soaks (24-72h). The CI job runs a 60s stress for
signal; the full soak per issue #5677 needs staging.
* All compression/TLS combinations. The harness's defaults are
uncompressed + clear-text; matrix expansion is future work.
* Listener-port collisions across parallel CI runs. INFRA_ID
isolates docker-network names but the TAP_GROUP-scoped MYSQLX_
PROXYSQL_PORT (default 6603) is a single value. CI runs are
serial per workflow concurrency group; not a problem today but
worth flagging if matrix-fanout is added.
|
4 weeks ago |
|
|
7e70c347f3 |
test(mysqlx): wire harness into the docker-isolated TAP framework
Per user direction: never run proxysql directly outside the testing
environment. The harness scripts at test/scripts/mysqlx/ are correct
as Python clients, but their assumed invocation ('run them against a
hand-started proxysql') was wrong. The proper integration is the
existing docker-isolated TAP harness, which already brings up
ProxySQL + backends in containers on a private docker network.
This commit lays the framework groundwork for that integration. It is
NOT yet a complete invocation of the harness — that requires a docker
image rebuild (mysql-connector-python is not in proxysql-ci-base) and
a TAP-test wrapper, both documented in the new
test/tap/groups/mysqlx-soak/README.md TODO list.
## What landed
* test/infra/control/start-proxysql-isolated.bash:
- Optional plugin .so bind-mount when PROXYSQL_LOAD_MYSQLX_PLUGIN=1.
Mounts ${WORKSPACE}/plugins/mysqlx/ProxySQL_MySQLX_Plugin.so at
/usr/lib/proxysql/ProxySQL_MySQLX_Plugin.so inside the container.
Fails fast with a clear message if the .so is missing.
- Optional per-group config override via PROXYSQL_CONFIG_OVERRIDE.
Lets a group ship a proxysql-ci.cnf that declares plugins=("...")
so the chassis loads the plugin at Phase A — the generic config
has no plugins= line, by design.
* test/tap/groups/mysqlx-soak/ (new group):
- env.sh: sets PROXYSQL_LOAD_MYSQLX_PLUGIN=1, PROXYSQL_CONFIG_OVERRIDE
pointing at the per-group .cnf, SKIP_CLUSTER_START=1 (single-node
proxysql is enough), and the X-protocol port constants the
setup-infras.bash hook + harness scripts share.
- infras.lst: just infra-dbdeployer-mysql84 (existing 3-node MySQL
8.4 with X-protocol on classic+20000 by dbdeployer convention).
- proxysql-ci.cnf: copy of the generic config with one extra block:
plugins=("/usr/lib/proxysql/ProxySQL_MySQLX_Plugin.so")
- setup-infras.bash: standard group-setup hook. Waits for
mysqlx_users admin table to appear (sanity-check that the
plugin loaded at all), then provisions one route, one user, one
endpoint via admin SQL, reloads to runtime, and verifies the
mysqlx listener bound on port 6603.
- README.md: documents the four remaining work items needed to
actually invoke the harness as a TAP test (add mysql-connector-
python to docker-base, wrap harness as a TAP entry, register in
groups.json, wire into CI).
This commit is intentionally narrow: it adds the framework wiring
that lets a future commit invoke the harness from inside the
test-runner container. Anyone with the four TODO items completed can
run the harness against a real chassis-loaded ProxySQL via:
WORKSPACE=$(pwd) INFRA_ID=dev-$USER TAP_GROUP=mysqlx-soak \
test/infra/control/ensure-infras.bash
— which is the canonical TAP-harness entry point per CLAUDE.md.
The standalone Python harnesses at test/scripts/mysqlx/ remain
runnable for ad-hoc dev validation, but they are no longer the
primary path; the docker-isolated TAP group is.
|
4 weeks ago |
|
|
fe91e290d8 |
test(mysqlx): add behavioural-validation and stress harnesses
Three companion harnesses for the post-merge confidence work tracked
in issues #5677 (smoke + soak), #5678 (behavioural validation), and
#5681 (stress test). These are NOT TAP unit tests — they require live
infrastructure (a real MySQL 8.x and a running ProxySQL with the
mysqlx plugin loaded). They post-date the merge window and exist to
let an operator with a staging environment reproduce the validation.
* test/scripts/mysqlx/README.md — setup recipe (ProxySQL admin
config, MySQL backend bring-up via docker or dbdeployer, the
invocation lines for both harnesses).
* test/scripts/mysqlx/behavioral_validation.py — exercises two
scenarios from issue #5678. Scenario 1 ("SIGTERM mid-traffic")
opens N X-Protocol clients running steady SELECT loops, sends
SIGTERM to proxysql, then verifies each client received a clean
Mysqlx::Error frame with code 1053 ("Server is shutting down")
rather than an unannounced TCP RST. Exercises
MysqlxSession::shutdown_notify_client (commit
|
4 weeks ago |
|
|
83725ea4e5 |
feat: add --no-plugins kill switch; fix 4 pre-existing test failures
## (1) --no-plugins kill switch (issue #5680) When the plugin chassis is enabled (PROXYSQL40 builds), an operator upgrading to v4.0.0 gets the chassis active by default. If a critical chassis bug is found post-release, the recovery options today are: - Roll back the entire ProxySQL package to v3.x. - Edit the config file to comment out plugins=() and restart. Add a runtime kill switch — a CLI flag (and equivalent env var) that bypasses plugin loading entirely, regardless of config. Cuts the time-to-recover dramatically and reduces deployment anxiety. CLI: --no-plugins (gated by PROXYSQL40) Env: PROXYSQL_NO_PLUGINS=1 (CLI takes priority) Field: GloVars.no_plugins Wired through: when set, LoadConfiguredPlugins / InitConfiguredPlugins / StartConfiguredPlugins / StopConfiguredPlugins all become no-ops. LoadConfiguredPlugins emits a single startup log line so the operator knows the bypass took effect: Plugin chassis disabled by --no-plugins / PROXYSQL_NO_PLUGINS=1; skipping load of N configured plugin(s) Verified: --no-plugins appears in proxysql --help. The bypass message string is in the binary. Full end-to-end smoke against a Docker MySQL deferred to issue #5677. ## (2) plugin_manager_unit-t #62 + #88 (issue #5679) Test bug. The two assertions encoded the pre-ab9d5a103 contract that "destructor skips stop on plugins that were never started". Commit |
4 weeks ago |
|
|
09c15d6d54 |
fix(mysqlx): reject re-auth on active session; fix two pre-existing test issues
## (A) Re-authentication on an active session is now rejected Addresses the Important finding from the security re-review of PR #5651 (see https://github.com/sysown/proxysql/issues/5676). After a successful login the session is in WAITING_CLIENT_XMSG. Before this commit, dispatch_client_message routed `SESS_AUTHENTICATE_START` and `SESS_AUTHENTICATE_CONTINUE` into the auth handlers unconditionally. The handlers overwrote `username_`, `identity_`, `target_hostgroup_`, `target_address_`, `target_port_` — but they did NOT tear down `backend_conn_`. The next StmtExecute was forwarded over the previous user's pooled backend connection. The proxy then audited the query as user B while the backend executed it as user A's role — a real identity-coherence / audit hazard. The X Protocol uses `Mysqlx::Session::Reset` for re-auth on the same connection, not direct re-auth. Reject `SESS_AUTHENTICATE_START` / `SESS_AUTHENTICATE_CONTINUE` when `status_ == WAITING_CLIENT_XMSG` with code 1845 (FATAL) and drop the session. Conformant with the spec. Also clears `auth_challenge_` on successful auth (defense in depth): the verified challenge is no longer reachable by a stale AuthenticateContinue replay even before the dispatch-level guard fires. The unit test `test_error_severity_non_fatal` previously took a shortcut: it manually set `status_=WAITING_CLIENT_XMSG` then sent AUTHENTICATE_START to drive the auth flow. With the re-auth rejection now in place, that shortcut hits the new guard and the test hangs waiting for an auth challenge that never comes. Updated the test to drive the auth flow naturally from CONNECTING_CLIENT (the state init() leaves the session in), which exercises the same code paths without the now-invalid pre-auth status_ override. ## (B) mysqlx_config_store_concurrent_unit-t: missing variables DDL This was the source of 6 pre-existing test failures surfaced during the ASAN run on PR #5651 (4, 11, 12, 13, 14, 15). All asserted that load_from_runtime atomically replaces previously-loaded data. They failed because the test fixture's create_runtime_db() did not create a `runtime_mysqlx_variables` table, but `load_from_runtime` queries that table near the end: SELECT variable_name, variable_value FROM runtime_mysqlx_variables When the table doesn't exist, fetch_result returns false and load_from_runtime short-circuits BEFORE swapping the new identities/ routes/endpoints into place. Every "second load replaces first" assertion silently failed because the second load never actually replaced anything — the swap never happened. This is the same bug that was fixed in `mysqlx_config_store_pure_unit-t.cpp` in commit |
4 weeks ago |
|
|
baeca0e3dc |
test: silence SonarCloud BUG: name truncate-via-temporary in clear_log()
Three identical SonarCloud BUG-severity findings (one per file) on the
truncate-via-temporary idiom:
std::ofstream(g_log_path, std::ios::trunc);
This creates a temporary std::ofstream whose destructor closes the file
— the truncate is the intended side effect. SonarCloud's rule "Name
this unused temporary object or remove it" does not understand the
side-effect pattern and flags it as a BUG.
Issue #5674 triaged all 3 BUG findings as false positives. This commit
silences them with the cosmetic fix recommended in that issue: give
the temporary a name and (void)-cast it. Same generated code, no
behaviour change, but Sonar stops flagging it.
Files: test/tap/tests/unit/plugin_{config,lifecycle,manager}_unit-t.cpp
|
4 weeks ago |
|
|
df7e335e23 |
fix(ci,infra): pass PROXYSQL40 to plugin build, remove orphaned infra files
Three CI/infra clean-ups that fall out of the independent review. 1) .github/workflows/CI-mysqlx.yml: pass PROXYSQL40=1 (and the implied tier flags) to `make` when building the mysqlx plugin. plugins/mysqlx/Makefile picks up tier flags from the environment and propagates them as -DPROXYSQL40 / -DPROXYSQL31 / -DPROXYSQLFFTO / -DPROXYSQLTSDB / -DPROXYSQLGENAI on every compile line. If the workflow runs `make` with no flags, the plugin is built without -DPROXYSQL40 — meaning the ProxySQL_PluginDescriptor and ProxySQL_PluginServices struct layouts compiled into the plugin .so differ from the layouts that the cached src/proxysql binary (built upstream by CI-trigger with the full tier flags) sees. The link succeeds and the first virtual dispatch into a plugin callback crashes or, worse, corrupts memory silently. The Makefile already warns about exactly this in lines 56-61. Pass the flags explicitly. 2) test/tap/groups/mysqlx-e2e/infras.lst + test/infra/docker-compose-mysqlx.yml: delete both — they are orphaned. `infras.lst` referenced `infra-mysqlx`, which has never existed under `test/infra/`. ensure-infras.bash would have errored on it — except `mysqlx-e2e/env.sh` exports SKIP_PROXYSQL=1, which makes ensure-infras.bash short-circuit at line 38 before it reaches the docker-compose loop. So infras.lst was both wrong AND unreachable — the worst combination for the next reader trying to figure out how the e2e group is wired. Similarly, `test/infra/docker-compose-mysqlx.yml` was a docker-compose file that no `infra-*/` directory points at, left over from an early plan to use Docker for the mysqlx backend that was abandoned in favour of dbdeployer. Both files are dead weight; delete them. 3) test/tap/groups/mysqlx-e2e/env.sh: comment the unconventional wiring so the next reader doesn't have to reverse-engineer it. Document why this group has no `infras.lst` / no `infra-mysqlx/` dir, why CI uses inline dbdeployer instead of ensure-infras.bash, and that setup-infras.bash + pre-cleanup.bash exist for local-only ad-hoc use today. 4) test/tap/tests/Makefile: drop the dangling `test_mysqlx_listener_smoke-t` target. That test was retired together with the dormant MysqlxWorker path in commit 98aee7db2; the unit/Makefile no longer builds it. The wrapper target in test/tap/tests/Makefile remained and would fail `make test_mysqlx_listener_smoke-t` with "no rule to make target". Replace with a NOTE pointing at where the listener-lifecycle coverage actually lives now (mysqlx_thread_unit-t, mysqlx_robustness_unit-t). Verified: the plugin still builds clean with the tier flags exported to the sub-make. No behavioural change for the docker-using groups. |
4 weeks ago |
|
|
04bccec51e |
chore(plugin-chassis): tighten gating, drop dead paths, gate forgery setters
Five clean-up items from the independent review of PR #5651. None of these change behaviour on a normal run; they each fix a concrete way the current code is misleading or unnecessarily exposed. 1) lib/ProxySQL_Admin.cpp: gate the three plugin-DB-handle getters (proxysql_plugin_get_admindb / _configdb / _statsdb) under #ifdef PROXYSQL40. Previously these were defined unconditionally and emitted symbols into v3.0/v3.1 binaries. The chassis is a v4.0 feature; the user explicitly required that v3.x builds carry no plugin-aware code. Wrap in PROXYSQL40 so they are entirely absent from v3.x linkage. ProxySQL_PluginManager.cpp's extern declarations (lines 23-25) are already inside the file-wide PROXYSQL40 gate and so resolve only when the gate is active. 2) lib/ProxySQL_PluginManager.cpp + include/ProxySQL_PluginManager.h: delete the dead `#else /* !PROXYSQL40 */` branches. Both files are wrapped in a top-level `#ifdef PROXYSQL40` covering the entire body. Inner `#ifdef PROXYSQL40 ... #else ... #endif` blocks therefore had unreachable `#else` arms — 30+ lines of "pre-chassis two-phase loader" in the .cpp, plus a redundant declaration of proxysql_load_configured_plugins in the .h. The dead arms read as load-bearing alternative implementations on review and that is exactly the wrong signal. Drop them; the single PROXYSQL40 path is the only one. 3) lib/Admin_Bootstrap.cpp + include/proxysql_admin.h + src/main.cpp: remove ProxySQL_Admin::materialize_plugin_tables(). `Admin::init()` already merges plugin-declared schemas into tables_defs_{admin,config,stats} (~line 944) and runs the DDL via check_and_build_standard_tables() (~line 994), all on the same first-boot/reload code path the core tables use. The follow-up call to GloAdmin->materialize_plugin_tables() in main.cpp ran a second name-dedup pass that found everything already present and produced an empty new-rows set — i.e. the post-init helper was a no-op disguised as load-bearing infrastructure. Delete the helper, the header declaration, and the main.cpp call site, and update the comments in main.cpp + ProxySQL_PluginManager.cpp to point at Admin::init() as the single canonical materialization site. Leave a NOTE in Admin_Bootstrap.cpp at the old call site so anyone re-adding a similar helper sees why the prior one was removed. 4) plugins/mysqlx/include/mysqlx_session.h + plugins/mysqlx/src/mysqlx_session.cpp: gate the two genuine forgery vectors behind MYSQLX_TEST_BUILD. inject_identity_for_test() bypasses the full auth flow — no credential check, no capability negotiation, just sets identity_ to a caller-supplied MysqlxResolvedIdentity. resolve_backend_target_ for_test() drives a private routing helper without an authenticated identity. Both are necessary for unit tests but should not be reachable at all in shipped binaries; an in-process exploit reaching the session can call inject_identity_for_test() to forge an authenticated identity. Wrap them in #ifdef MYSQLX_TEST_BUILD; define -DMYSQLX_TEST_BUILD in the test Makefile only. The remaining target_*_for_test() getters are read-only state observers and are left unconditional — they cannot mutate the session and a debugger could observe the same state regardless. 5) test/tap/tests/unit/Makefile: define -DMYSQLX_TEST_BUILD on every unit test compile line via OPT. This is the test-only knob that re-enables the gated forgery methods so unit tests still compile. plugins/mysqlx/Makefile does NOT define this macro, so the production .so does not compile in the entry points. Verified locally: - plugins/mysqlx/ProxySQL_MySQLX_Plugin.so builds clean with PROXYSQL40=1 PROXYSQL31=1 PROXYSQLFFTO=1 PROXYSQLTSDB=1 PROXYSQLGENAI=1 (no MYSQLX_TEST_BUILD). - test/tap/tests/unit/mysqlx_robustness_unit-t builds and runs: 74/74 assertions pass, including the ones that exercise inject_identity_for_test (visible only because the test Makefile defines MYSQLX_TEST_BUILD). |
4 weeks ago |
|
|
9f5ed235b8 |
fix(build,test groups): unblock CI on plugin-chassis
Two unrelated CI blockers, fixed together because each one alone leaves
the pipeline red and they are trivially independent:
1) `make cleanbuild` (and any other goal that recurses into plugins/mysqlx
on a v3.0/v3.1 box without libprotobuf-dev) failed in
plugins/mysqlx/Makefile because the protobuf-3.x ABI check fires at
parse time. The check is correct for *building* the plugin — running
pre-generated .pb.cc against an ABI-incompatible libprotobuf would
produce a .so that links cleanly and crashes on first virtual
dispatch — but it has no business firing for `clean`/`cleanall`,
which only delete object files. Wrap the check in
`ifeq ($(filter clean cleanall,$(MAKECMDGOALS)),)` so the safety
guarantee is preserved on build paths and clean is now usable on a
bare host. CI-builds was failing every job at Makefile:540 cleanbuild
for this reason, and the failure cascaded through every dependent
test workflow.
2) `mysqlx_compression_unit-t` was added in the X-Protocol Phase-1/2/3
compression commits but never registered in `test/tap/groups/groups.json`.
The lint workflow `check_groups.py --source` flagged it as
"executable test missing from groups.json" and exited 1, blocking
the entire CI run. Add the entry to `unit-tests-g1` with the
`@proxysql_min_version:4.0` tag, matching every other mysqlx unit
test in the file.
Also restore six MySQL test entries that lost their `mysql90-g3`,
`mysql95-g3` tags during the
|
4 weeks ago |
|
|
aef01ef0be |
feat(mysqlx): compress outbound server frames (Phase 3)
Phase 3 of three-phase X Protocol compression support: server→client
compression on outbound frames. Wraps up the MVP — CapabilitiesSet
negotiation (Phase 1), inbound decompression (Phase 2), and now
outbound compression all roundtrip.
What this commit does
=====================
forward_frame_to_client() — the chokepoint for backend→client frame
forwarding — now routes through send_to_client_compressed(), which:
1. Returns early to plain client_ds_.enqueue_frame() when compression
is not negotiated OR the body is below COMPRESSION_MIN_OUTPUT_BYTES
(50 bytes — same threshold the upstream MySQL X plugin uses; per-
message envelope + framing overhead would otherwise dwarf savings).
2. With combine_mixed_messages = false: emits one Compression frame
per body. The protobuf has server_messages set to the original
frame's msg_type and uncompressed_size set to the original body
length, so a spec-compliant client can decompress in place.
3. With combine_mixed_messages = true: appends a fully-framed copy
of the body to compress_batch_framed_ and bumps compress_batch_count_.
Once the count reaches max_combine_messages (defaulting to 64 if
the client didn't supply one), or flush_compression_batch() is
invoked at a natural boundary, all buffered frames are emitted as
one Compression message with NEITHER server_messages nor
client_messages set — payload is the concatenated stream of framed
X messages, matching the spec's third payload shape.
The flush points are:
- handler_waiting_server_msg() when it sees a terminal frame (end
of a result set / final OK / etc.) — the response is "done" so
anything still buffered must reach the wire before we go back to
WAITING_CLIENT_XMSG.
- handler_session_reset_waiting() on the ERROR path before
write_to_net(), same reasoning.
Mid-response we deliberately do NOT flush — that would defeat the
combine_mixed_messages benefit by emitting a Compression message per
batch hit, which is exactly what we're trying to avoid for streaming
result sets. The count cap bounds how long a single batch can grow.
Compressor selection mirrors Phase 2:
- zstd_stream uses ZSTD_compressCCtx() with a per-session ZSTD_CCtx
that's lazily allocated and freed in reset_compression_state().
- lz4_message uses LZ4_compress_default() one-shot.
On compressor failure (ZSTD_isError or lz4 returning <= 0) the helper
falls back to enqueueing the body uncompressed — losing compression
benefit beats dropping the message. The session itself stays healthy.
Tests
=====
mysqlx_compression_unit-t now plans 64 sub-tests, all passing:
- Phase 1: 22 sub-tests for capability negotiation
- Phase 2: 17 sub-tests for inbound decompression
- Phase 3 (new, 25 sub-tests):
- zstd round-trip: frame on the wire is COMPRESSION with
server_messages = NOTICE; payload decompresses back to the
exact original 200-byte body
- lz4 round-trip, same shape
- below-threshold passthrough: 20-byte body emitted as plain
NOTICE, not COMPRESSION (verifies the fast path)
- combine_mixed_messages with max_combine_messages=3: three
successive sends produce ONE Compression frame whose
decompressed payload contains all three NOTICE bodies in
order, with neither server_messages nor client_messages set
- compression-disabled passthrough: when no negotiation, the
helper acts as a plain enqueue_frame() (proves a client that
never opts in is unaffected)
A few new test-only accessors expose the batch state and
send_to_client_compressed() entry point so tests can exercise the
output path without wiring a fake backend (which would block on
connect() in the dispatcher anyway).
Verification
============
Top-level `PROXYSQLGENAI=1 make` builds cleanly. mysqlx_compression_unit-t
passes 64/64. plugin_lifecycle_unit-t (26/26) passes unchanged.
mysqlx_session_unit-t still has its two pre-existing failures at
sub-tests 33-34 (auth flow), unrelated to compression and present on
this branch before the Phase 1 commit.
|
4 weeks ago |
|
|
b1fd6b31fc |
feat(mysqlx): decompress incoming Compression messages (Phase 2)
Phase 2 of three-phase X Protocol compression support: client→server
decompression. Compression on the server→client path (Phase 3) still
goes out uncompressed; CapabilitiesSet stores the negotiation in
Phase 1 and this commit consumes it.
What this commit does
=====================
When the client sends a Mysqlx.Connection.Compression message AND
compression has been negotiated, we now:
1. Parse the Compression protobuf — payload bytes, optional
uncompressed_size hint, optional client_messages tag.
2. Decompress the payload using the negotiated algorithm:
- zstd_stream: streaming decompression via a ZSTD_DCtx that
persists across messages on the same session (per spec —
successive Compression frames may continue a single zstd
stream, so we cannot recreate the context per frame).
- lz4_message: one-shot LZ4_decompress_safe. The X spec defines
lz4_message as one independent frame per message, so no
persistent context is needed.
3. Feed the decompressed bytes back into client_ds_.feed_bytes() so
the existing frame parser picks them up. Two payload shapes per
spec are handled:
- client_messages set: payload is one decompressed body of that
type — we re-frame with a 5-byte X header in front.
- neither set: payload is already a sequence of fully-framed
X messages — fed verbatim.
4. The dispatch loop re-enters on the same handler tick (to_process
set), so a Compression-wrapped StmtExecute runs end-to-end without
an extra network roundtrip.
If client_messages is unset and server_messages IS set, the message
is rejected (5008): server_messages on the c→s path is always wrong.
Anti-bomb / bounds
==================
COMPRESSION_MAX_DECOMPRESSED_BYTES = 16 MiB caps how much output a
single Compression message can produce, mirroring MysqlxDataStream's
existing on-the-wire X_MAX_PAYLOAD_SIZE so a Compression frame never
expands beyond what the rest of the data plane can handle anyway. If
the client provides an uncompressed_size hint smaller than 16 MiB we
honor that as the tighter bound. Hint of 0 with non-empty payload is
treated as malformed.
For zstd, the decompression loop re-checks the cap before each
ZSTD_decompressStream call and bails (with 5008) the moment the
output buffer would exceed it. A no-progress condition (zout.pos == 0
with input remaining) also bails — that catches malformed streams
that would otherwise spin forever.
For lz4, LZ4_decompress_safe(dstCapacity = cap) naturally enforces
the limit: the decompressor refuses to write past dstCapacity and
returns an error code we map to 5008.
Linkage / build
===============
The plugin .so is dlopen'd with RTLD_LOCAL, so symbols from libzstd
/ liblz4 that the proxysql binary may already pull in are NOT
visible to the plugin. This commit links the static
deps/zstd/zstd/lib/libzstd.a + deps/lz4/lz4/lib/liblz4.a archives
directly into the .so so the plugin is self-contained.
The session header forward-declares ZSTD_DCtx / ZSTD_CCtx so the
zstd headers don't leak through include/mysqlx_session.h into other
translation units.
Tests
=====
mysqlx_compression_unit-t now covers Phase 2 end-to-end (39 sub-
tests total, all passing):
- Phase 1: capability negotiation (22 sub-tests, unchanged)
- decompress zstd_stream client_messages=SQL_STMT_EXECUTE,
inner StmtExecute reaches dispatch (no 5008, session moves
past WAITING_CLIENT_XMSG)
- same for lz4_message
- oversize bomb attempt: lie about uncompressed_size, send
a 1 MiB-of-zeros payload — rejected with 5008
- garbage compressed payload: rejected with 5008
- sanity: COMPRESSION before negotiation still 5008
Verification
============
Top-level `PROXYSQLGENAI=1 make` builds cleanly; the plugin .so
links against the static zstd + lz4 archives. plugin_lifecycle_unit-t
(26/26) passes unchanged. mysqlx_session_unit-t still has its two
pre-existing failures at sub-tests 33-34, identical to behavior
before this commit (verified by stashing only the Phase 2 edits to
plugins/mysqlx/{src,include}/* + Makefile and rebuilding). The
mysqlx_thread_unit-t / mysqlx_concurrent_unit-t hangs are also
pre-existing and reproduce on the unmodified branch.
|
4 weeks ago |
|
|
f19be5f3a0 |
feat(mysqlx): negotiate X Protocol compression capability (Phase 1)
Phase 1 of three-phase X Protocol compression support: capability
negotiation only. The COMPRESSION message itself is still rejected
with error 5008 in dispatch_client_message(); Phase 2 wires up
decompression on input and Phase 3 wires up compression on output.
What this commit does
=====================
- send_capabilities() now advertises a `compression` capability listing
the algorithms the plugin can support: zstd_stream and lz4_message.
Both libraries (libzstd, liblz4) are already statically linked into
libproxysql.a / pulled into the unit-test link line, so this does not
introduce any new runtime dependency.
- handler_capabilities_set() detects when a client sets the `compression`
capability and parses the OBJECT value's sub-keys:
- `algorithm` (required string) — must match an advertised value;
anything else is rejected with X-Protocol error 5052 (the
capability-prepare-failed code per the spec).
- `server_combine_mixed_messages` / `combine_mixed_messages` (bool)
- `server_max_combine_messages` / `max_combine_messages` (uint)
Both spelling variants are accepted because mysql-connector-python
emits the short form while libmysqlclient emits the spec form, and
the upstream MySQL server tolerates both.
- Negotiation outcome is stored on MysqlxSession via three new members
(compression_algo_, compression_combine_mixed_messages_,
compression_max_combine_messages_). Phase 2 / Phase 3 will read
these to drive (de)compression. They are reset by both init() and
reset() so a session reuse does not inherit stale negotiation.
- Unsupported algorithms (e.g. deflate_stream) and structurally
malformed values (wrong protobuf type, missing algorithm field) are
rejected with a non-fatal X-Protocol Error frame — the session
remains healthy so the client can either retry CapabilitiesSet or
proceed without compression.
Why 5052 (non-fatal) and not 5008
---------------------------------
5008 is the runtime "compression message arrived but compression is
disabled" error and stays in dispatch_client_message() for now. 5052
is the spec-defined "capability prepare failed" status used during the
CapabilitiesSet handshake; treating an unknown algorithm as a
capability error matches the upstream MySQL X plugin's behavior and
lets compliant clients downgrade to no-compression on the same
connection.
Tests
=====
New unit test: test/tap/tests/unit/mysqlx_compression_unit-t.cpp
(22 sub-tests, all passing). Covers:
- CapGet response advertises `compression` with both algorithms
- CapSet zstd_stream + combine hints accepted, stored on session
- CapSet lz4_message accepted, stored on session
- CapSet deflate_stream rejected with 5052 (non-fatal), session
remains healthy with no algorithm set
- CapSet with wrong-shape compression value (scalar instead of
object) rejected with 5052
Existing mysqlx_session_unit-t / plugin_lifecycle_unit-t still pass
(the two pre-existing failures in mysqlx_session_unit-t at sub-tests
33-34, "auth succeeded for correct password" and "session in
WAITING_CLIENT_XMSG after auth", are present on this branch before
this commit and unrelated to compression — verified by stashing only
the mysqlx_session.{cpp,h} edits and re-running).
Build infra fix piggy-backed on this commit
-------------------------------------------
test/tap/tests/unit/Makefile referenced
$(SQLITE3_LDIR)/../libsqlite_rembed.a in the GenAI-tier link line,
but that .a is no longer produced on this branch (it was the artifact
of the now-removed sqlite-rembed Rust extension). Without removing
this stale reference, no plugin/mysqlx unit test can link, which
blocks verifying the new compression test alongside the existing
mysqlx tests required by the task. Mirrors the upstream fix that
already landed on sibling branches as commit
|
4 weeks ago |
|
|
ae88c07089 |
Fix GTID range validation
|
1 month ago |
|
|
7ca0d153cc
|
Merge pull request #5654 from sysown/fix/pgsql-active-tx-on-broken-conn
fix(pgsql): surface mid-transaction backend errors instead of silently replaying |
1 month ago |
|
|
5d702b12bf |
build(test): fix testgalera link after switch to src/SQLite3_Server.cpp
CI-maketest / builds (testgalera) has been red on every branch since
commit
|
1 month ago |
|
|
f776af5487 |
test(pgsql): harden tx_poisoned tests after review
Driven by the test-coverage review findings. Seven substantive changes across both test files: 1. NoticeResponse payload is now inspected (review 1.1/1.2). Install PQsetNoticeReceiver with a NoticeBag collector. Assert the poison NoticeResponse has severity=WARNING, sqlstate=01000, and non-empty message; and that NO notice carries sqlstate 57P01 (backend-leak) or 00000 (wrong pre-fix code). Without this, the no-57P01-leak invariant called out in issue #5658 was unverified. 2. COMMIT-on-poisoned notice payload is inspected (review 1.4 / 3.3). Case B now asserts the 25P01 "there is no transaction in progress" notice is emitted alongside the synthesized ROLLBACK command tag — the other half of the PG-native parity contract. 3. ROLLBACK TO SAVEPOINT, AND CHAIN, multi-statement, and ROLLBACKET word-boundary are exercised (review 1.3/1.14). Added as a batch alongside SELECT 42 and RELEASE SAVEPOINT, each asserted to return 25P02 and stay poisoned. 4. Autocommit-no-poison (case C) + admin-off-no-counter-move (case D) are now explicit (review 1.8 / 2.4). Pre-fix behavior: a non-tx statement killed mid-flight bumped the total counter because the feature used IsActiveTransaction() (polluted by the disconnect heuristic). Case C confirms the is_in_transaction() tightening. Case D confirms that toggling the admin var off truly disables the feature (no counter movement), not just preserves client termination. 5. Counter deltas are EXACT (==), not >= (review 2.1). Recovery test's +1/+1/+6 and ext-query test's +3 are all equality-checked. A bug that over-counts (e.g. regressed to per-wire-packet accounting) would be caught. 6. Flakiness-resistance (review 4.1/4.2/4.3/4.4/5.3). The killer no longer sleeps 500 ms blindly; it polls pg_stat_activity up to 6 s for the marker backend and reports a clean diag-plus-skip if the kill didn't fire. This is the same pattern used by the sibling retry_guard test. kill_delivered is now surfaced on the return struct so the caller can distinguish "feature regressed" from "CI infra flaked". 7. Admin-variable hygiene (review 5.1/6.4). - RAII-scoped RestorePreserveClientAdminVar: restore to default (=true) on every exit path including failure. - UPDATE now uses the full 'pgsql-<name>' prefix on variable_name; the previous WHERE clause matched zero rows and silently left the runtime value unchanged (which is how the pre-fix case D appeared to pass PQstatus checks while counters still moved). - After LOAD PGSQL VARIABLES TO RUNTIME, open a burst of short- lived PGconns to trigger activity on every PgSQL worker, guaranteeing each thread's next poll() wake-up picks up the new __thread-local admin-var value. Eliminates the up-to-2s refresh lag (pgsql-poll_timeout) that otherwise leaves stale worker state when case D runs. Severity / severity (ext-query test only): the rejected_25P02_as_error() predicate now also checks severity=="ERROR", catching a regression that might emit FATAL 25P02 (libpq would close the socket on FATAL despite the 25P02 code). Verified: both tests pass 17/17 and 11/11 against a live legacy-g2 infra. Case D cleanly shows counters unchanged when admin is off; case C cleanly shows counters unchanged for an autocommit kill. |
1 month ago |
|
|
100e417179 |
test(pgsql): extended-query coverage for tx_poisoned behavior
New sibling to pgsql-tx_poisoned_recovery-t, plus a one-line semantics
fix in the extended-query poison gate.
Semantics fix (lib/PgSQL_Session.cpp):
Before, the pgsql_tx_poisoned_rejected_statements_total counter was
incremented on EVERY swallowed ext-query wire packet — one per Parse /
Bind / Describe / Close / Execute / Sync. That made a single logical
PQexecParams call count as 4+, inconsistent with the simple-query
path where a 'Q' packet bumps it exactly once.
Now P/B/D/C/E are silently swallowed (no counter bump), and Sync is
the single accounting point — the counter value matches the number
of client-visible "rejected statements" regardless of protocol.
New test pgsql-tx_poisoned_extended_query-t (plan(11)):
* Poison the session via a simple-query pg_sleep + mid-tx kill.
* While poisoned:
- PQexecParams("SELECT 42", 0 params) returns 25P02.
- PQprepare("stmt_poisoned", "SELECT 43") returns 25P02.
- PQexecPrepared on that name returns 25P02.
* The rejected counter increments by exactly 3 (one per logical
ext-query call), not by the 8-11 wire packets that libpq actually
sends. This assertion IS the mechanical proof that the semantics
fix above took effect.
* Simple-query ROLLBACK recovers the session.
* Post-recovery PQexecParams and PQprepare+PQexecPrepared both
execute cleanly and return rows.
Registered alongside the simple-query sibling in legacy-g2. Verified
against a live legacy-g2 infra: both tests pass (11/11 and 15/15),
counter deltas exactly match expected per-statement semantics.
|
1 month ago |
|
|
eec1a07d9c |
test(pgsql): fix tx_poisoned-recovery test against a live infra
Two small fixes caught by running the test against the local legacy-g2 infra: 1. Connect to ProxySQL admin via the PgSQL-protocol admin port (cl.pgsql_admin_host / cl.pgsql_admin_port = 6132), not the MySQL-protocol admin port (6032). libpq on 6032 gets back the MySQL server greeting byte and fails with "expected authentication request from server, but received J". All three counter reads and the admin-variable toggles go through the same helper, so this single flip fixes both flows. 2. plan(15), not plan(16). The test has 15 distinct ok() assertions; the prior plan(16) left one slot unfilled and the TAP runner reported the test as failed even when every assertion passed. With both fixes, the test now passes 15/15 against the live legacy-g2 infra (PgSQL 16 single-node). counters before/after the ROLLBACK path: total 6->7 , recovered 4->5 , rejected 6->8 (two rejects = one for SELECT 42 while poisoned, one for RELEASE SAVEPOINT while poisoned). |
1 month ago |
|
|
f1135ad453 |
test(pgsql): acceptance test for tx_poisoned recovery feature
pgsql-tx_poisoned_recovery-t covers the whole UX flow added by the
preceding commit and the admin-var-off fallback:
Case A — ROLLBACK recovery path
* Mid-tx backend kill produces ErrorResponse severity=ERROR sqlstate=25P02
(asserts no leak of the original FATAL / 57P01).
* PQstatus stays CONNECTION_OK, PQtransactionStatus is PQTRANS_INERROR.
* Any non-end-of-tx statement while poisoned returns 25P02.
* RELEASE SAVEPOINT while poisoned returns 25P02 (matches PG native).
* ROLLBACK returns PGRES_COMMAND_OK and the session goes to PQTRANS_IDLE.
* A subsequent SELECT 1 succeeds on a different backend pid than the
one that died (discovered via pg_stat_activity from a direct
superuser connection, since pg_backend_pid() via ProxySQL returns
thread_session_id, not the real backend pid — see the sibling
pgsql-retry_guard_in_txn_on_broken_backend-t).
* The three new stats counters (pgsql_tx_poisoned_total,
pgsql_tx_poisoned_recovered_total,
pgsql_tx_poisoned_rejected_statements_total) are read from
stats_pgsql_global via the admin port and asserted to have
incremented.
Case B — COMMIT recovery path
* COMMIT inside a poisoned tx returns PGRES_COMMAND_OK with command
tag 'ROLLBACK' (matches PG native — PG itself rolls back on COMMIT
inside an aborted tx).
Case C — admin variable off
* Toggle pgsql-preserve_client_on_broken_backend_in_tx=false, repeat
the mid-tx kill, assert the client session is terminated (pre-
feature fallback behavior preserved). The admin variable is
restored to true at test exit so subsequent tests in the group
see the default.
Registered in legacy-g2 alongside its sibling regression guard so
both run together on the same infra.
Related: issue #5658.
|
1 month ago |
|
|
abda5410ea |
chore(CI): Remove regular mysql56-single infra
Signed-off-by: Wazir Ahmed <wazir@proxysql.com> |
1 month ago |
|
|
8857543c4d |
test(pgsql): identify backend via pg_stat_activity instead of pg_backend_pid()
The first CI run of pgsql-retry_guard_in_txn_on_broken_backend-t (now
registered in legacy-g2) failed at "pg_terminate_backend signalled
successfully" because ProxySQL intercepts pg_backend_pid() and returns
its own thread_session_id (see PgSQL_Protocol.cpp:1398), not the real
backend PID.
Postgres server log from the failing run made this unambiguous:
[239] LOG: statement: BEGIN
[239] LOG: statement: SELECT pg_sleep(3)
[240] LOG: statement: SELECT pg_terminate_backend(22)
[240] WARNING: PID 22 is not a PostgreSQL backend process
[239] LOG: statement: ROLLBACK
Real backend is PID 239. "22" came from ProxySQL's fake-PID response,
so the kill went nowhere, pg_sleep(3) ran to completion, and the post-
fix FATAL_ERROR assertion never had a chance to be exercised — the
regression guard was trivially passing the bug through.
Replace the pg_backend_pid() probe with a pg_stat_activity lookup
issued from the direct superuser connection:
- embed a unique literal marker ("retry_guard_marker_<time>_<pid>")
in the sleep query so the backend running it is trivially
identifiable;
- do the find + terminate in one PQexecParams round-trip against
pg_stat_activity, so the pid can't change between lookup and kill.
plan() drops from 6 to 5 because we no longer have a separate "got a
pid" assertion. On a build that includes
|
1 month ago |
|
|
e24ac092f6 |
test(mysql): enlarge grace close binlog to ~50 MB to un-flake target>8s iterations
fast_forward_grace_close-t writes a binlog, then for each target_time in
{0..7, 20, 30, 60} reads it via a throttled client and asserts that
target_time <= 8s reaches EOF and target_time > 8s does not (because the
8s grace_close_ms should cut the session before the binlog is drained).
The >8s iterations have been flaky on GitHub runners. Analysis of the
actual CI logs (proxysql.log timestamps vs test TAP output) shows what
goes wrong: during the 8s grace window, ProxySQL keeps pushing bytes
into the client's kernel recv buffer as fast as the buffer accepts them.
If the whole binlog — including the empty-event EOF marker — fits into
"what the client has already read" + "what is sitting in the client's
recv buffer" by t=8s, grace_close does fire and cut the session, but
the client's next mysql_binlog_fetch just returns the already-buffered
EOF event and reports reached_EOF=TRUE. The test then fails the
"Expected FALSE" assertion.
With total_bytes = N and client recv-buffer capacity R, the test is
only robust when N > ~1.7*R. Prior bumps (3 events -> 50 events,
2026-04-13) lifted N from 150 KB to 2.5 MB, which is enough on
dbdeployer but too close to the margin on GH runners whose TCP recv
autotune can grow past a couple of MB.
1000 x 50 KB = ~50 MB puts N well above any realistic R (kernels cap
autotune around a few MB), so the grace close always fires while there
is still many MB of undelivered binlog sitting in ProxySQL's output
queue — the client cannot reach EOF.
Side effects on other tests: none. The only other binlog-reading test
in the same group, fast_forward_switch_replication_deprecate_eof-t, is
already incidentally reading grace_close's binlog (it picks the first
file from SHOW BINARY LOGS, which ends up being grace_close's rotated
file). It reads at full speed and only asserts reached_EOF==true,
which stays correct — it just reports ~50 MB instead of ~2.5 MB in its
informational TAP message. Full-speed read of 50 MB over the Docker
bridge is sub-second per config (4 configs -> ~1-2 s added). Data
generation cost at test start is ~1-2 s for the extra INSERTs.
|
1 month ago |
|
|
51c44d10b2 |
TAP: parameterize session_track_variables helpers; add time_zone and sql_mode coverage
Context
-------
The four session_track_variables TAP tests previously hard-coded a single
variable, 'innodb_lock_wait_timeout', for their round-trip assertion. That
only exercised the integer path in
'MySQL_Session::handler_rc0_Process_Variables', leaving the string-value
path (and the character-set special case elsewhere in the same function)
untested. The stored-procedure helper was also named generically
('set_session_variable') while its body was pinned to InnoDB's lock wait
timeout -- confusing for readers.
Changes
-------
* test/tap/tests/session_track_variables.h:
- Introduce 'struct tracked_var_spec { name, set_expr; }' so the helpers
can exercise arbitrary session variables from a single
spec-driven code path.
- 'set_session_variable()' now takes a spec, builds a per-variable
stored procedure name ('test.set_session_track_<name>') so multiple
specs can coexist without stepping on each other, and guarantees
that the CALL is the last statement on the connection before the
tracker is read (any query in between would reset the session
tracker state).
- Add 'drop_session_variable_proc()' for optional teardown. Kept
separate from the set path so tests that need to preserve the CALL
as the last statement can skip cleanup.
- Switch the whole value surface from 'int' to 'std::string':
'extract_sess_var_mysql_pkt', 'select_sess_var_value', and
'extract_sess_var_proxy_internal' all return strings, which is how
session tracking delivers values on the wire and matches both
integer and string variables without encoding assumptions.
- Provide a default set, 'session_track_default_vars', with three
representative cases:
* 'innodb_lock_wait_timeout' (integer; original coverage)
* 'time_zone' (string, portable small value-space)
* 'sql_mode' (string, representative of production usage)
All three 'set_expr' values are pure server-side SQL (no client-side
randomization), so a CALL alone produces a fresh value per run.
* test/tap/tests/mysql-session_track_variables_optional-t.cpp,
test/tap/tests/mysql-session_track_variables_enforced-t.cpp,
test/tap/tests/mysql-session_track_variables_ff-t.cpp,
test/tap/tests/mysql-session_track_variables_ff_mysql56-t.cpp:
- Iterate over 'session_track_default_vars' and emit one TAP 'ok' per
(spec[, mode]) combination.
- Adjust plans accordingly. The ENFORCED-on-5.6 case still emits a
single 'ok' because the backend is rejected before any per-variable
tracking is attempted, so multiplying by the spec count there would
be misleading.
- Compare values as strings using the new string-returning helpers.
The broadened coverage does not change what 'handler_rc0_Process_Variables'
or 'handle_session_track_capabilities' do; it only exercises more of their
existing behavior, notably the non-integer value path and the
'proxysql_find_charset_*' branches that activate for character-set
variables (not exercised by these three specs but now reachable through
the same harness for follow-up tests).
|
1 month ago |
|
|
8da7a71a44 |
build(test): link ezoption_parser_unit-t / mysql_resolution_unit-t with WASAN
obj/tap.o is compiled with $(OPT), which includes $(WASAN) = -fsanitize=address when WITHASAN=1. Every other unit test binary goes through the pattern rule on line 333 which re-applies $(OPT) on the link line, pulling in libasan. The two explicit rules for ezoption_parser_unit-t and mysql_resolution_unit-t were written without $(OPT) on the link step (they avoid linking libproxysql.a since they are standalone header-only tests), but they also dropped $(WASAN) — so the linker sees ASAN-instrumented tap.o and nothing to resolve __asan_report_*, __asan_init, __asan_handle_no_return, etc. against: /usr/bin/ld: obj/tap.o: undefined reference to `__asan_report_load8' ... (hundreds more) ... collect2: error: ld returned 1 exit status make[1]: *** [Makefile:321: ezoption_parser_unit-t] Error 1 Put $(WASAN) back on both link commands. CI-unit-tests-asan-coverage has been red on every branch (including v3.0 itself) since at least 2026-04-12 because of this. |
1 month ago |
|
|
c2200e472d |
ci(lint): catch TAP tests missing from groups.json on every PR
Previously CI-lint-groups-json only triggered when groups.json itself was
edited and only checked formatting. That can't catch the "author added a
new test source but forgot to register it" case (which is exactly what
happened with pgsql-retry_guard_in_txn_on_broken_backend-t before this
series).
- Drop the paths filter so the workflow runs on every pull_request/push.
- Add a --source mode to check_groups.py that scans test/tap/tests* for
*-t.{cpp,sh,py,php} (and extension-less -t scripts) and flags any
source file not registered in groups.json as an ERROR. Requires no
build — runs in seconds.
- The reverse direction (entry in groups.json with no matching source)
is a NOTE in source mode, because a handful of binaries are built
from differently-named sources via explicit Makefile targets (e.g.
mysql_reconnect_libmariadb-t from mysql_reconnect.cpp).
- Executable mode behavior is unchanged; run-multi-group.bash keeps
calling check_groups.py with no flag.
|
1 month ago |
|
|
292f6f6bae |
test(pgsql): register retry_guard_in_txn_on_broken_backend in groups.json
The test added in
|
1 month ago |
|
|
8e509d3711 |
test(pgsql): regression guard for silent in-transaction retry fix
Reproduces the bug fixed in the preceding commit: while a client is in an explicit transaction, terminating the backend mid-query (simulated via pg_terminate_backend from a separate superuser connection) must surface a fatal error to the client. Pre-fix ProxySQL silently retried the in-flight statement on a fresh backend as autocommit, so the expected PGRES_FATAL_ERROR came back as PGRES_TUPLES_OK and the next COMMIT landed on a connection with no open transaction. The test also asserts the client<->ProxySQL connection stays open and that ROLLBACK + a follow-up SELECT 1 recover the session cleanly. |
1 month ago |
|
|
8d94919b22 |
fix: preserve EOF capability in enforced mode
- Keep `CLIENT_DEPRECATE_EOF` enabled during frontend handshake when `session_track_variables=ENFORCED`. - Avoid unsafe mysql_error() calls in session-track TAP tests. Signed-off-by: Wazir Ahmed <wazir@proxysql.com> |
1 month ago |
|
|
c723ede0cf |
Merge remote-tracking branch 'origin/plugin-chassis' into ProtocolX-rebased
# Conflicts: # lib/ProxySQL_PluginManager.cpp # plugins/mysqlx/Makefile # plugins/mysqlx/include/mysqlx_plugin.h # plugins/mysqlx/include/mysqlx_session.h # test/tap/groups/groups.json # test/tap/tests/test_mysqlx_listener_smoke-t.cpp # test/tap/tests/unit/Makefile |
1 month ago |
|
|
b3d4de0bc8 |
Merge remote-tracking branch 'origin/v3.0' into plugin-chassis
# Conflicts: # test/tap/groups/groups.json |
1 month ago |
|
|
d2e03fae36 |
fix(test groups): resolve groups.json conflict + tag plugin tests for v4.0
The `test/tap/groups/groups.json` on `origin/v3.0` was reformatted and expanded (mysql95 targets added, legacy-g1..g5 merged into mysql84-g1..g5, etc.) in commits that landed after `plugin-chassis` branched. Merging `plugin-chassis -> v3.0` therefore produced a content conflict in this file. Resolve by taking `origin/v3.0`'s current `groups.json` as the base and re-adding every plugin-chassis and mysqlx-plugin test entry on top, each tagged with `@proxysql_min_version:4.0` per the existing tier convention (`test_mcp_static_harvest-t`, `anomaly_detection-t`, etc. already use this pattern). Tests tagged v4.0: * Plugin-chassis unit tests (7): plugin_config_unit-t, plugin_dispatch_unit-t, plugin_manager_unit-t, plugin_registry_unit-t, plugin_query_hook_unit-t, plugin_prometheus_unit-t, plugin_lifecycle_unit-t * Mysqlx-plugin unit tests (22): test_mysqlx_plugin_load-t, test_mysqlx_admin_tables-t, test_mysqlx_listener_smoke-t, mysqlx_config_store_unit-t, mysqlx_config_store_concurrent_unit-t, mysqlx_config_store_pure_unit-t, mysqlx_protocol_unit-t, mysqlx_protocol_socket_unit-t, mysqlx_route_store_unit-t, mysqlx_stats_unit-t, mysqlx_admin_schema_unit-t, mysqlx_admin_commands_unit-t, mysqlx_admin_disk_commands_unit-t, mysqlx_data_stream_unit-t, mysqlx_connection_unit-t, mysqlx_session_unit-t, mysqlx_thread_unit-t, mysqlx_message_dispatch_unit-t, mysqlx_concurrent_unit-t, mysqlx_backend_auth_unit-t, mysqlx_credential_verify_unit-t, mysqlx_robustness_unit-t, mysqlx_tls_unit-t * Mysqlx E2E tests (2, group `mysqlx-e2e-g1`): test_mysqlx_e2e_handshake-t, test_mysqlx_e2e_routing-t Formatting is preserved from v3.0 (one entry per line, alphabetically sorted, 2-space indent). Entries that existed only on plugin-chassis under the old per-line layout and were never in v3.0 are now inserted in the correct alphabetical position. |
1 month ago |
|
|
e20876a451 |
fix(tests): repair pre-existing mysqlx test build breakage
Under `export PROXYSQLGENAI=1 && export PROXYSQL40=1 && make debug -j &&
make build_tap_test_debug -j` the tap build failed with ~78 errors
spread across several mysqlx tests. None were caused by the chassis
work; they are drift between test code and current APIs that no plain
build had ever exercised (unit builds tried PROXYSQL40 without DEBUG;
the debug path uncovers them).
Changes:
* test/tap/tests/unit/mysqlx_route_store_unit-t.cpp (19 sites),
test/tap/tests/unit/mysqlx_stats_unit-t.cpp (7 sites),
test/tap/tests/unit/mysqlx_admin_commands_unit-t.cpp (1 site),
test/tap/tests/unit/mysqlx_admin_disk_commands_unit-t.cpp (2 sites):
the `// NOSONAR:` comment was placed BEFORE the closing `)` of
`SQLite3DB::open(..., FLAGS);`, commenting out both the flags and the
closing paren. Move the NOSONAR comment to end of line and restore
the flags argument.
* test/tap/tests/unit/mysqlx_stats_unit-t.cpp (28 sites):
`record_conn_ok/err/used` added a second argument (destination
hostgroup) in
|
1 month ago |
|
|
f34dc4573a |
fix(tap tests): gate test_mysqlx_*-t under PROXYSQL40
test/tap/tests/Makefile's tests-cpp target uses `$(wildcard *-t.cpp)`
to pick up all test sources. test_mysqlx_e2e_handshake-t.cpp,
test_mysqlx_e2e_routing-t.cpp, test_mysqlx_listener_smoke-t.cpp,
test_mysqlx_admin_tables-t.cpp and test_mysqlx_plugin_load-t.cpp all
reference chassis types (ProxySQL_PluginServices, mysqlx_config_store.h)
that only exist in the public headers under -DPROXYSQL40.
Under a plain v3.0 build (`unset PROXYSQLGENAI && unset PROXYSQL40 &&
make debug -j && make build_tap_test_debug -j`), the wildcard still
matched them, and the generic `%-t: %-t.cpp` recipe tried to compile
them -- producing 130+ `error:` lines (mysqlx_config_store.h not
found, Mysqlx::Datatypes::* conversion failures, ProxySQL_PluginServices
undeclared, etc.). Reported by the user.
Fix: autodetect PROXYSQL40 via `nm libproxysql.a | grep -c
invoke_register_schemas_phase` (same probe the unit Makefile uses) and
filter out `test_mysqlx_*` from the wildcard when the chassis symbol is
absent. Under PROXYSQL40 the wildcard is unmodified and all mysqlx
tests are built as before.
Verification:
* `unset PROXYSQLGENAI && unset PROXYSQL40 && make debug -j &&
make build_tap_test_debug -j` -> 0 errors, builds complete.
- proxysql binary built (122 MB)
- ProxySQL_MySQLX_Plugin.so NOT built (skipped by top-level Makefile)
- 51 unit tests built, 0 plugin/mysqlx unit tests, 0 mysqlx tests/
tests -> chassis is completely invisible to v3.0.
|
1 month ago |
|
|
99494b015d |
chore(tap): Fix lint errors in groups.json
Signed-off-by: Wazir Ahmed <wazir@proxysql.com> |
1 month ago |
|
|
b65ba99118 |
fix(unit tests): gate plugin + mysqlx tests behind PROXYSQL40
After the previous commit made the plugin chassis invisible in v3.x
builds (no ProxySQL_PluginManager, no ProxySQL_PluginServices types
available from public headers), the unit-test Makefile still listed
all plugin/mysqlx tests in the unconditional UNIT_TESTS base list.
`make build_tap_test_debug` (no PROXYSQL40) then attempted to compile:
* test/tap/test_helpers/fake_plugin.cpp — uses ProxySQL_PluginServices,
ProxySQL_PluginCommandResult, ProxySQL_PluginDescriptor at file
scope; none of these exist under !PROXYSQL40.
* test/tap/tests/unit/plugin_{config,dispatch,manager,registry}_unit-t —
reference ProxySQL_PluginManager's public API.
* test/tap/tests/unit/mysqlx_*_unit-t + test_mysqlx_*-t — include
plugins/mysqlx/include/mysqlx_*.h which transitively include
ProxySQL_Plugin.h and use chassis types.
Reported by user with a `make debug && make build_tap_test_debug`
invocation that produced 121 `error:` lines and failed to link.
Move every plugin-chassis and mysqlx-plugin unit test out of the base
UNIT_TESTS list and into the existing `ifeq ($(PROXYSQL40),1)` block.
v3.x builds now build 23 core unit tests (smoke, query_cache, query
processor, protocol, auth, hostgroups, FFTO, etc.) and zero chassis
artifacts; PROXYSQL40 builds add the 31 plugin/mysqlx tests on top.
Verification:
* `unset PROXYSQLGENAI && unset PROXYSQL40 && make debug -j &&
make build_tap_test_debug -j` — 0 errors, 23 unit tests built,
fake_plugin.so not even attempted.
* `PROXYSQLGENAI=1 make debug -j && PROXYSQLGENAI=1 make
build_tap_test_debug -j` — 0 errors, full chassis + mysqlx test
suite builds (54 unit tests).
|
1 month ago |
|
|
baa5069eaf |
CI: Add `mysql56-single` test infra
Signed-off-by: Wazir Ahmed <wazir@proxysql.com> |
1 month ago |
|
|
3ba92815f8 |
fix(plugin-chassis): make chassis fully invisible in v3.x builds
Review feedback identified that the chassis was leaking into the v3.0
stable build via unfenced references in core code:
* Admin_Bootstrap.cpp had `if (auto* m = proxysql_get_plugin_manager())`
and a full materialize_plugin_tables() implementation outside any
PROXYSQL40 fence
* proxysql_admin.h declared materialize_plugin_tables()
* proxysql_glovars.hpp held GloVars.plugin_modules and
proxysql_load_plugin_modules_from_config()
* ProxySQL_GloVars.cpp had three unfenced .clear()/use sites
* ProxySQL_Admin.cpp::dispatch_plugin_admin_command (template + two
instantiations) was unfenced
* src/main.cpp's GloPluginManager, LoadConfiguredPlugins,
InitConfiguredPlugins, StartConfiguredPlugins, StopConfiguredPlugins,
UnloadPlugins teardown, the four-phase orchestration block, and the
proxysql_load_plugin_modules_from_config call were all unfenced
Separately, Admin_Handler.cpp held 16 hardcoded MYSQLX alias vectors
(LOAD_MYSQLX_USERS_FROM_MEMORY, etc.) and a 16-deep if-ladder that
called resolve_admin_alias_to_canonical(). This embedded plugin-specific
knowledge in core code -- core should know nothing about any specific
plugin's commands.
The agreed architecture: v3.0/v3.1 builds have NO plugin loader at all;
the entire plugin chassis (including its public manager surface, its
loader, and its dispatch helpers) only exists under PROXYSQL40. v3.0
core code therefore holds zero plugin-related code paths.
Changes:
* include/ProxySQL_Plugin.h, include/ProxySQL_PluginManager.h,
lib/ProxySQL_PluginManager.cpp: wrap entire file body in
`#ifdef PROXYSQL40 ... #endif`. Including the header from a v3.x
translation unit yields nothing; the .cpp compiles to an empty object
file. Removed redundant inner PROXYSQL40 fences inside the now-empty
v3.x body of Plugin.h (kept the few that are inside the file-wide
outer for clarity). PROXYSQL_PLUGIN_ABI_VERSION is now unconditionally
2 (the macro is no longer reachable from a v3.x compile, so the
PROXYSQL40-vs-1 split is moot).
* include/proxysql_glovars.hpp, lib/ProxySQL_GloVars.cpp: gate
GloVars.plugin_modules field, all .clear() sites, the
proxysql_load_plugin_modules_from_config declaration + definition.
* include/proxysql_admin.h: gate materialize_plugin_tables and
dispatch_plugin_admin_command<S> declarations.
* lib/Admin_Bootstrap.cpp: gate `#include "ProxySQL_PluginManager.h"`,
the `if (auto* m = proxysql_get_plugin_manager())` merge block, and
the materialize_plugin_tables definition.
* lib/Admin_Handler.cpp: delete the 16 LOAD_/SAVE_MYSQLX_* const
std::vector<std::string> declarations entirely. Delete the helper
resolve_admin_alias_to_canonical(). Delete the 16-deep if-ladder
+ the !PROXYSQL40 fallback dispatch branch. The remaining plugin
dispatch is one generic call to
proxysql_resolve_configured_plugin_admin_alias() inside an
#ifdef PROXYSQL40 block; v3.x compiles it out entirely. Core now
holds no plugin-specific knowledge of any kind.
* lib/ProxySQL_Admin.cpp: gate dispatch_plugin_admin_command template
body + both explicit instantiations.
* src/main.cpp: gate `#include "ProxySQL_PluginManager.h"`,
GloPluginManager declaration, all four wrapper functions
(LoadConfiguredPlugins / InitConfiguredPlugins /
StartConfiguredPlugins / StopConfiguredPlugins), the
StopConfiguredPlugins call inside UnloadPlugins, the four-phase
orchestration in ProxySQL_Main_init_phase2___not_started, the
GloVars.plugin_modules.clear() and the
proxysql_load_plugin_modules_from_config call in
ProxySQL_Main_process_global_variables. v3.x builds reduce that
whole block to a single ProxySQL_Main_init_Admin_module call.
* plugins/mysqlx/src/mysqlx_plugin.cpp,
plugins/mysqlx/src/mysqlx_admin_schema.cpp: drop the !PROXYSQL40
fallback paths. The plugin only loads under PROXYSQL40 now (no
loader exists in v3.x), so the legacy combined-init code path and
the 16 fallback register_command() calls were dead code. The
descriptor unconditionally wires register_schemas; mysqlx_init holds
only context setup.
* Makefile (top-level): the four build_src_* recipes that recurse into
plugins/mysqlx are wrapped in `$(if $(filter 1,$(PROXYSQL40)),...)`.
v3.x builds emit "[skip] mysqlx plugin (PROXYSQL40 not set)" instead
of building the .so. Clean targets stay unconditional.
* test/tap/tests/unit/mysqlx_admin_alias_resolution_unit-t.cpp:
delete the test (it covered resolve_admin_alias_to_canonical, which
is itself deleted). Remove from unit Makefile UNIT_TESTS list.
Verification:
* v3.0 stable build (`make`, no flags):
- Produces 147 MB src/proxysql binary
- `nm src/proxysql | grep -cE 'invoke_register_schemas_phase|GloPluginManager|materialize_plugin_tables'` -> 0
- mysqlx plugin .so is correctly skipped: "[skip] mysqlx plugin (PROXYSQL40 not set)"
* PROXYSQLGENAI=1 build (cascades PROXYSQL40/31/FFTO/TSDB):
- Produces 200 MB src/proxysql binary with chassis symbols
- mysqlx plugin .so built (9.2 MB), contains mysqlx_register_schemas
* All 5 plugin unit tests pass under PROXYSQL40:
plugin_config_unit-t 48/48
plugin_dispatch_unit-t 52/52
plugin_lifecycle_unit-t 26/26
plugin_query_hook_unit-t 46/46
plugin_prometheus_unit-t 10/10
|
1 month ago |
|
|
885712c679 |
Merge branch 'v3.0' into session-track-system-variable
|
1 month ago |
|
|
ab9d5a1036 |
fix(plugin-chassis): address deep-review findings
Follow-up to
|
1 month ago |