Module 13: PostgreSQL Source Code
This module prepares you to read, understand, and contribute to the PostgreSQL codebase. You’ll learn the code structure, key patterns, and how to set up a development environment. Practical context: The PostgreSQL codebase is approximately 1.3 million lines of C, developed over 35+ years by hundreds of contributors. It is widely regarded as one of the best-structured large C codebases in existence. The code is heavily commented, follows consistent conventions, and uses patterns that were battle-tested long before “clean code” was a popular concept. If you can read PostgreSQL source, you can read virtually any C codebase.Estimated Time: 14-16 hours
Difficulty: Expert
Prerequisite: Complete Modules 7-9 (internals)
Outcome: Ready for first contribution
Difficulty: Expert
Prerequisite: Complete Modules 7-9 (internals)
Outcome: Ready for first contribution
13.1 Repository Structure
Key Directories Deep Dive
- src/backend/parser
- src/backend/optimizer
- src/backend/executor
- src/backend/storage
SQL Parsing
13.2 Development Environment Setup
Building from Source
Build Options Explained
Practical tip: Never use-O0 for performance testing — the optimizer makes a dramatic difference in PostgreSQL’s performance (often 2-3x). Use -O0 -g3 for debugging with GDB/LLDB where you need accurate variable inspection, and -O2 -g for realistic performance profiling. Assertions (--enable-cassert) add about 10-15% overhead, so disable them for benchmarks but always enable them during development — they catch subtle bugs that would otherwise manifest as data corruption in production.
IDE Setup
13.3 Code Conventions
Naming Conventions
Common Patterns
Memory Contexts
Memory Contexts
Error Handling
Error Handling
Node System
Node System
List Operations
List Operations
13.4 Key Data Structures
Understanding these three structures is like learning the nouns of the PostgreSQL language. Nearly every function you will read in the codebase accepts, returns, or manipulates aRelation, a HeapTuple, or a Buffer. Master these and the rest of the code becomes dramatically more readable.
Relation (Table)
HeapTuple
Practical tip: AHeapTuple is a pointer to tuple data, not a copy of it. If the buffer containing the tuple is released, the HeapTuple becomes a dangling pointer. When you need a tuple to survive beyond the current buffer lock, use heap_copytuple() to create an independent copy in the current memory context.
Buffer
13.5 Tracing Code Flow
Example: SELECT Query Path
Using GDB
Practical tip: Do not attach GDB to the postmaster process. Instead, connect with psql first, then attach GDB to the specific backend process serving your session. RunSELECT pg_backend_pid(); in psql to find your PID, then gdb -p <pid>. This avoids accidentally freezing the postmaster (which would block all new connections) and lets you debug a single session in isolation.
13.6 Adding a Simple Feature
The best way to learn a codebase is to make a small change to it. These two examples — adding a configuration parameter and adding a SQL function — are the PostgreSQL equivalents of “Hello, World.” They touch just enough of the infrastructure to teach you the patterns without requiring deep domain expertise.Example: Add New GUC Parameter
Example: Add New SQL Function
13.7 Running Tests
Practical tip: Always runmake check before submitting a patch. The PostgreSQL community takes regressions very seriously — a patch that introduces even one test failure will be rejected immediately. Run make check-world for the most thorough validation, but be aware it can take 10-30 minutes depending on your hardware. For iterative development, make check TESTS="your_test" gives fast feedback on just the tests relevant to your change.
Writing Tests
13.8 Key Source Files to Study
Practical tip: Start withtcop/postgres.c and exec_simple_query(). This is the “main loop” of query processing — every SELECT, INSERT, UPDATE, and DELETE flows through here. Once you understand this function, you can follow any query from entry point to result. Read it with the call trace from Section 13.5 open in a second window. After postgres.c, costsize.c is the next most rewarding file to study because it reveals exactly how the planner assigns costs — knowledge that directly improves your ability to tune queries in production.
13.9 Practice Exercise
Exercise: Add Execution Time to EXPLAIN
Exercise: Add Execution Time to EXPLAIN
Goal: Add “Planning Time: X ms” output to regular EXPLAIN (not just ANALYZE)Steps:
- Find where EXPLAIN output is generated (
commands/explain.c) - Study
ExplainOnePlan()function - Add timing capture before/after planning in
ExplainOneQuery() - Output the timing in
ExplainPrintPlan() - Write regression tests
- Submit patch to pgsql-hackers
src/backend/commands/explain.csrc/test/regress/sql/explain.sqlsrc/test/regress/expected/explain.out
Next Module
Module 14: Contributing to PostgreSQL
Submit your first patch to PostgreSQL