Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.
|Comment:||Add initial words for the assert.html document. Clearly label the document as a work-in-progress for now.|
|Timelines:||family | ancestors | descendants | both | branch-3.22|
|Files:||files | file ages | folders|
|User & Date:||drh 2018-02-13 15:40:22|
|17:08||Text clarification and typo fixes on the copyright.html page. check-in: 8a0f41df1a user: drh tags: branch-3.22|
|15:40||Add initial words for the assert.html document. Clearly label the document as a work-in-progress for now. check-in: 076b02c111 user: drh tags: branch-3.22|
|20:35||Fix typo in the vtab.html document. check-in: ec9c8be989 user: drh tags: branch-3.22|
1 +<title>The Use Of assert() In SQLite</title> 2 + 3 +<table_of_contents> 4 + 5 +<h1 style="color:red;">Work In Progress - Do Not Link!</h1> 6 +<p style="color:red;font-size:150%;"> 7 +This document is a work-in-progress and is not yet ready for release. 8 +Please do not link to it, yet. 9 +</p> 10 + 11 +<h1>Assert() And Other Assert()-like Macros In SQLite</h1> 12 + 13 +<p> 14 +The assert(X) macro is 15 +[https://en.wikipedia.org/wiki/Assert.h|part of standard C], in the the 16 +<assert.h> header file. 17 +SQLite adds three other assert()-like macros named NEVER(X), ALWAYS(X), 18 +and testcase(X). 19 + 20 +<ul> 21 +<li><p><b>assert(X)</b> → 22 +The assert(X) statement indicates that the condition X is always true. 23 +In other words, X is an invariant. The assert(X) macro works like a 24 +procedure in that it has no return value. 25 + 26 +<li><p><b>ALWAYS(X)</b> → 27 +The ALWAYS(X) function indicates that condition X is always true as far 28 +as the developers know, but there is not proof the X is true, or the 29 +proof is complex and error-prone, or the proof depends on implementation 30 +details that are likely to change in the future. ALWAYS(X) behaves like 31 +a function that returns the boolean value X, and is intended to be used 32 +within the conditional of an "if" statement. 33 + 34 +<li><p><b>NEVER(X)</b> → 35 +The NEVER(X) function indicates that condition X is never true. This 36 +is the negative analog of the ALWAYS(X) function. 37 + 38 +<li><p><b>testcase(X)</b> → 39 +The testcase(X) statement indicates that X is sometimes true and sometimes 40 +false. In other words, testcase(X) indicates that X is definitely not an 41 +invariant. Since SQLite uses 100% [MC/DC testing], the presence of a 42 +testcase(X) macro indicates that not only is it possible for X to be either 43 +true or false, but there are test cases to demonstrate this. 44 +</ul> 45 + 46 +<p> 47 +SQLite version 3.22.0 ([dateof:3.22.0]) contains 5290 assert() macros, 48 +839 testcase() macros, 88 ALWAYS() macros, and 63 NEVER() macros. 49 + 50 +<h2>Philosophy of assert()</h2> 51 + 52 +<p>In SQLite, the presence of assert(X) means that the developers have 53 +a proof that X is always true. Readers can depend upon X being true to 54 +help them reason about the code. An assert(X) is a strong statement 55 +about the truth of X. There is no doubt. 56 + 57 +<p>The ALWAYS(X) and NEVER(X) macros are a weaker statement about the 58 +truth of X. The presence of ALWAYS(X) or NEVER(X) means that the developers 59 +believe X is always or never true, but there is no proof, or the proof 60 +is complex and error-prone, or the proof depends on other aspects 61 +of the system that seem likely to change. 62 + 63 +<p>In other systems, developers sometimes use assert(X) in a way that is 64 +similar to the use of ALWAYS(X) in SQLite. Developers will add an 65 +assert(X) as a 66 +[https://blog.regehr.org/archives/1576|tacit acknowledgement that they 67 +do not fully believe that X is always true]. 68 +We believe that this use of assert(X) is wrong and violates the intent 69 +and purpose of having assert(X) available in C in the first place. 70 +An assert(X) should not be seen as a safety-net or top-rope used to 71 +guard against mistakes. Nor is assert(X) appropriate for defense-in-depth. 72 +An ALWAYS(X) macro, or something similar, should be used in those cases 73 +because ALWAYS(X) is followed by code to actually deal with the problem. 74 + 75 +<p>The [https://golang.org|Go programming language] omits assert(). 76 +The Go developers 77 +[https://golang.org/doc/faq#assertions|recognize this is contentious]. 78 +Disallowing assert() is essentially telling developers that they are 79 +not allowed to expression invariants. It is as if the developers of 80 +Go do not want coders to prove that the software is correct. 81 +The SQLite developers believe that the lack of assert() disqualifies 82 +Go as a language for serious development work. 83 + 84 +<h2>Different Behaviors According To Build Type</h2> 85 + 86 +<p>Three separate builds are used to validate the SQLite software. 87 +A functionality testing build is used to validate the source code. 88 +A coverage testing build is used to validate the test suite, to confirm 89 +that the test suite provides 100% MC/DC. The release build is used 90 +to validate the machine code. 91 +All tests must give the same answer in all three 92 +builds. See the [testing|"How SQLite Is Tested"] document for more detail. 93 + 94 +<p>The assert() macros behave differently according to how SQLite is built. 95 + 96 +<center> 97 +<table border=1> 98 +<tr><th><th>Functionality Testing<th>Coverage Testing<th>Release</tr> 99 +<tr><th valign="top">assert(X) 100 +<td>abort() if X is false 101 +<td>no-op 102 +<td>no-op 103 +</tr> 104 +<tr><th valign="top">ALWAYS(X) 105 +<td>abort() if X is false 106 +<td>always true 107 +<td>pass through the value X 108 +</tr> 109 +<tr><th valign="top">NEVER(X) 110 +<td>abort() if X is true 111 +<td>always false 112 +<td>pass through the value X 113 +</tr> 114 +<tr><th valign="top">testcase(X) 115 +<td>no-op 116 +<td>do some harmless work if X is true 117 +<td>no-op 118 +</tr> 119 +</table> 120 +</center> 121 + 122 +<p>The default behavior of assert(X) in standard C is that it is enabled 123 +for release builds. We find this acceptable in general. However, the 124 +SQLite code base has many assert() statements in performance-sensitive 125 +areas of the code. Leaving assert(X) turned causes SQLite to run about 126 +three times slower. Also, SQLite strives to provide 100% MC/DC in an 127 +as-delivered configuration, which is obviously impossible if assert(X) 128 +statements are enabled. For these reasons, assert(X) is a no-op for 129 +release builds in SQLite.