1# TimescaleDB code style guide 2 3Source code should follow the 4[PostgreSQL coding conventions](https://www.postgresql.org/docs/current/static/source.html). This 5includes 6[source formatting](https://www.postgresql.org/docs/current/static/source-format.html) 7with 4 column tab spacing and layout rules according to the BSD style. 8 9## SQL and PL/pgSQL style 10 11There is no official SQL or PL/pgSQL style guide for PostgreSQL that 12we are aware of, apart from the general spacing and layout rules 13above. For now, try to follow the style of the surrounding code when 14making modifications. We might develop more stringent guidelines in 15the future. 16 17## Error messages 18 19Error messages in TimescaleDB should obey the PostgreSQL 20[error message style guide](https://www.postgresql.org/docs/current/static/error-style-guide.html). 21 22## C style 23 24While the PostgreSQL project mandates that 25[C code adheres to the C89 standard](https://www.postgresql.org/docs/current/static/source-conventions.html) 26with some exceptions, we've chosen to allow many C99 features for the 27clarity and convenience they provide. PostgreSQL sticks with C89 28mostly for compatibility with many older compilers and platforms, such 29as Visual Studio on Windows. Visual Studio should support most of C99 30nowadays, however. We might revisit this decision in the future if it 31turns out to be a problem for important platforms. 32 33Unfortunately, PostgreSQL does not have a consistent style for naming 34of functions, variables and types. This 35[mailing-list thread](https://www.postgresql.org/message-id/1221125165.5637.12.camel%40abbas-laptop) 36elaborates on the situation. Instead, we've tried our best to develop 37a consistent style that roughly follows the style of the PostgreSQL 38source code. 39 40### Declarations before code 41 42C99 supports having code before a declaration, similar to C++, and we 43also support this in the code. For instance, the following code 44follows the guidelines: 45 46```C 47void some_function() 48{ 49 prepare(); 50 int result = fetch(); 51 ... 52} 53``` 54 55### Function and variable names 56 57For clarity and consistency, we've chosen to go with lowercase 58under-score separated names for functions and variables. For instance, 59this piece of code is correct: 60 61```C 62static void 63my_function_name(int my_parameter) 64{ 65 int my_variable; 66 ... 67} 68``` 69 70while this one is wrong: 71 72```C 73static void 74MyFunctionName(int myParameter) 75{ 76 int myVariable; 77 ... 78} 79``` 80 81### Type declarations 82 83New composite/aggregate types should be typedef'd and use 84UpperCamelCase naming. For instance, the following is correct: 85 86```C 87typedef struct MyType 88{ 89 ... 90} MyType; 91``` 92 93while the following is wrong: 94 95```C 96typedef struct my_type 97{ 98 ... 99} my_type; 100``` 101 102### Modular code and namespacing 103 104When possible, code should be grouped into logical modules. Such modules 105typically resemble classes in object-oriented programming (OOP) 106languages and should use namespaced function and variable names that 107have the module name as prefix. TimescaleDB's [Cache](../src/cache.c) 108implementation is a good example of such a module where one would use 109 110```C 111void 112cache_initialize(Cache *c) 113{ 114 ... 115} 116``` 117 118rather than 119 120```C 121void 122initialize_cache(Cache *c) 123{ 124 125} 126``` 127 128### Object-orientated programming style 129 130Even though C is not an object-oriented programming language, it is 131fairly straight-forward to write C code with an OOP flavor. While we 132do not mandate that C code has an OOP flavor, we recommend it when it 133makes sense (e.g., to achieve modularity and code reuse). 134 135For example, TimescaleDB's [cache.c](../src/cache.c) module can be 136seen as a _base class_ with multiple derived _subclasses_, such as 137[hypertable_cache.c](../src/hypertable_cache.c) and 138[chunk_cache.c](../src/chunk_cache.c). Here's another example of 139subclassing using shapes: 140 141```C 142typedef struct Shape 143{ 144 int color; 145 void (*draw)(Shape *, Canvas *); 146} Shape; 147 148void 149shape_draw(Shape *shape) 150{ 151 /* open canvas for drawing */ 152 Canvas *c = canvas_open(); 153 154 /* other common shape code */ 155 ... 156 157 shape->draw(shape, c); 158 159 canvas_close(c); 160} 161 162typedef struct Circle 163{ 164 Shape shape; 165 float diameter; 166} Circle; 167 168Circle blue_circle = { 169 .shape = { 170 .color = BLUE, 171 .draw = circle_draw, 172 }, 173 .diameter = 10.1, 174}; 175 176void 177circle_draw(Shape *shape, Canvas *canvas) 178{ 179 Circle *circle = (Circle *) shape; 180 181 /* draw circle */ 182 ... 183} 184 185``` 186 187There are a couple of noteworthy take-aways from this 188example. 189 190* Non-static "member" methods should take a pointer to the 191object as first argument and be namespaced as described above. 192* Derived modules can expand the original type using struct embedding, 193in which case the "superclass" should be the first member of the 194"subclass", so that one can easily upcast a `Circle` to a `Shape` or, 195vice-versa, downcast as in `circle_draw()` above. 196* C++-style virtual functions can be implemented with functions 197pointers. Good use cases for such functions are module-specific 198initialization and cleanup, or function overriding in a subclass. 199 200### Other noteworthy recommendations 201 202* Prefer static allocation and/or stack-allocated variables over 203 heap/dynamic allocation when possible. Fortunately, PostgreSQL has a 204 nice `MemoryContext` implementation that helps with heap allocation 205 when needed. 206* Try to minimize the number of included headers in source files, 207 especially when header files include other headers. Avoid circular 208 header dependencies by predeclaring types (or use struct pointers). 209 210 211For a general guide to writing C functions in PostgreSQL, you can 212review the section on 213[C-language functions](https://www.postgresql.org/docs/current/static/xfunc-c.html) 214in the PostgreSQL documentation. 215 216## Tools and editors 217 218We require running C code through clang-format before submitting a PR. 219This will ensure your code is properly formatted according to our style 220(which is similar to the PostgreSQL style but implement in clang-format). 221You can run clang-format on all of the TimescaleDB code using `make format` 222if you have clang-format (version >= 7) or docker installed. 223 224 225The following 226[Wiki post](https://wiki.postgresql.org/wiki/Developer_FAQ#What.27s_the_formatting_style_used_in_PostgreSQL_source_code.3F) 227contains links to style configuration files for various editors. 228