doc/agents/project-conventions.md
make build_deps -j4 # Build dependencies (first time only)
make build_lib -j4 # Build libproxysql.a
make build_tap_tests # Build all tests (includes unit tests)
make -j4 # Full build (deps + lib + binary)
Always verify make build_lib -j4 compiles successfully before submitting changes to lib/ or include/.
| Directory | Purpose | When to modify |
|---|---|---|
include/ | All headers (.h/.hpp) | When adding new declarations |
lib/ | Core library sources → compiled into libproxysql.a | When adding/modifying implementations |
src/ | Entry point (main.cpp) and daemon code | Rarely — avoid unless necessary |
test/tap/tests/unit/ | Unit tests (no infrastructure needed) | When adding unit tests |
test/tap/tests/ | E2E TAP tests (need running ProxySQL + backends) | When adding integration tests |
test/tap/test_helpers/ | Unit test harness (test_globals, test_init) | When extending test infrastructure |
doc/ | Documentation | When documenting features |
test/tap/tests/unit/, NOT in test/tap/tests/<descriptive_name>_unit-t.cpp or <descriptive_name>-t.cppEvery unit test MUST use the existing harness:
#include "tap.h"
#include "test_globals.h"
#include "test_init.h"
#include "proxysql.h"
// ... other headers for types you need
int main() {
plan(<number_of_tests>);
test_init_minimal(); // Always call first
// ... test functions with ok(), is(), etc.
test_cleanup_minimal(); // Always call last
return exit_status();
}
The harness provides:
Glo* global stubs (defined in test_globals.cpp)noise_failures, stop_noise_tools, etc.)test_init_auth(), test_init_query_cache(), test_init_query_processor()Edit test/tap/tests/unit/Makefile:
UNIT_TESTS := linemy_test-t: my_test-t.cpp $(TEST_HELPERS_OBJ) $(LIBPROXYSQLAR)
$(CXX) $< $(TEST_HELPERS_OBJ) $(IDIRS) $(LDIRS) $(OPT) \
$(LIBPROXYSQLAR_FULL) $(STATIC_LIBS) $(MYLIBS) \
$(ALLOW_MULTI_DEF) -o $@
tap.o directly from source (no cpp-dotenv dependency)libproxysql.a + test_globals.o + test_init.otest/tap/tests/unit/connection_pool_unit-t.cpp — good example of a unit testtest/tap/tests/unit/rule_matching_unit-t.cpp — good example with regex testingtest/tap/test_helpers/test_globals.cpp — what symbols are already stubbedinclude/ConnectionPoolDecision.h — good example of a standalone extracted headerUse #ifndef HEADER_NAME_H / #define HEADER_NAME_H / #endif.
The ProxySQL include chain has circular dependencies:
proxysql.h → proxysql_structs.h → proxysql_glovars.hpp
cpp.h → MySQL_Thread.h → MySQL_Session.h → proxysql.h (circular)
cpp.h → MySQL_HostGroups_Manager.h → Base_HostGroups_Manager.h → proxysql.h (circular)
When extracting functions from tightly-coupled classes, create a standalone header in include/ with its own include guard and no ProxySQL dependencies. Example: include/ConnectionPoolDecision.h.
PascalCase matching the class namePascalCase describing the featurev3.0 — main stable branch (DO NOT target PRs here for unit test work)v3.0-5473 — unit test feature branch (target PRs here for test-related changes)v3.0-<issue_number> (e.g., v3.0-5491)git checkout -b v3.0-<issue_number> v3.0-5473
Use git rebase, NOT git merge:
git fetch origin v3.0-5473
git rebase origin/v3.0-5473
# Resolve conflicts if any
git push --force-with-lease
(#5491)PascalCase with protocol prefixes (MySQL_, PgSQL_, ProxySQL_)snake_caseUPPER_SNAKE_CASE@brief, @param, @return(char *) casts on string literals are acceptable (codebase convention)ProxySQL supports both MySQL and PostgreSQL. When modifying one protocol's code, check if the same change is needed for the other:
| MySQL | PostgreSQL |
|---|---|
MySQL_Session | PgSQL_Session |
MySQL_Thread | PgSQL_Thread |
MySQL_HostGroups_Manager | PgSQL_HostGroups_Manager |
MySQL_Monitor | PgSQL_Monitor |
MySQL_Query_Processor | PgSQL_Query_Processor |
MySrvConnList | PgSQL_SrvConnList |
Some components share a template base (Base_Session, Base_HostGroups_Manager, Query_Processor<T>). Changes to the template cover both protocols.