relpipe-data/examples-tr-sqlite-custom-version.xml
branchv_0
changeset 285 a6df8cac399e
child 286 37c50bb1f36f
equal deleted inserted replaced
284:075d3d62d913 285:a6df8cac399e
       
     1 <stránka
       
     2 	xmlns="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/strana"
       
     3 	xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro">
       
     4 	
       
     5 	<nadpis>Using custom version of SQLite (LD_PRELOAD)</nadpis>
       
     6 	<perex>switch to a newer or modified version of library using a little hack</perex>
       
     7 	<m:pořadí-příkladu>03600</m:pořadí-příkladu>
       
     8 
       
     9 	<text xmlns="http://www.w3.org/1999/xhtml">
       
    10 		
       
    11 		<p>
       
    12 			One of reasons why we prefer shared libraries (<code>.so</code>) rather than static linking,
       
    13 			is that shared libraries are much more hacker-friendly and allow the user switching to a newer or modified library without recompiling the program.
       
    14 		</p>
       
    15 		
       
    16 		<p>
       
    17 			By default, <code>relpipe-tr-sql</code> links to the SQLite library available in our distribution (e.g. 3.22).
       
    18 			As we can check:
       
    19 		</p>
       
    20 		
       
    21 		<m:pre jazyk="text"><![CDATA[$ ldd $(which relpipe-tr-sql) | grep sqlite
       
    22     libsqlite3.so.0 => /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007f4c73888000)]]></m:pre>
       
    23 	
       
    24 		<p>
       
    25 			But what if we want to use some new features like <a href="https://www.sqlite.org/windowfunctions.html">window functions</a> that are available in later (3.25) library versions?
       
    26 			Or what if we want to add our own custom modifications to this library?
       
    27 			Do we have to recompile the <m:name/> tools?
       
    28 		</p>
       
    29 		
       
    30 		<p>
       
    31 			No, we can just plug the new/modified library in and use it instead of the distribution one.
       
    32 		</p>
       
    33 		
       
    34 		<h2>Download and compile SQLite library</h2>
       
    35 		
       
    36 		<p>
       
    37 			The build process of SQLite should be straightforward:
       
    38 		</p>
       
    39 		
       
    40 		<m:pre jazyk="bash"><![CDATA[
       
    41 # Switch to the user for such experiments (optional but recommended):
       
    42 su - hacker
       
    43 
       
    44 # Create directories, download and extract sources:
       
    45 mkdir -p ~/src/sqlite
       
    46 cd ~/src/sqlite
       
    47 wget https://www.sqlite.org/2019/sqlite-autoconf-3300100.tar.gz
       
    48 tar xvzf sqlite-autoconf-3300100.tar.gz
       
    49 cd sqlite-autoconf-3300100/
       
    50 			
       
    51 # Optional: do some changes to the source code
       
    52 
       
    53 # Build SQLite:
       
    54 ./configure
       
    55 make
       
    56 
       
    57 # Test it:
       
    58 echo "SELECT 'hello world'" | ./sqlite3
       
    59 ]]></m:pre>
       
    60 
       
    61 		<p>
       
    62 			The desired shared libraries are located in the <code>.libs</code> directory.
       
    63 		</p>
       
    64 		
       
    65 		<h2>Use this library in the <m:name/> tools</h2>
       
    66 		
       
    67 		<p>
       
    68 			We have already build/installed <code>relpipe-tr-sql</code> which is linked to the SQLite library available in our distribution.
       
    69 			Then switching to a custom version of the library is very easy – we just need to set an environment variable.
       
    70 		</p>
       
    71 		
       
    72 		<m:pre jazyk="bash"><![CDATA[export LD_PRELOAD=~/src/sqlite/sqlite-autoconf-3300100/.libs/libsqlite3.so.0]]></m:pre>
       
    73 		
       
    74 		<p>And then <code>relpipe-tr-sql</code> will use the newer library version as we can check:</p>
       
    75 		
       
    76 		<m:pre jazyk="text"><![CDATA[$ ldd $(which relpipe-tr-sql) | grep sqlite
       
    77     /home/hacker/src/sqlite/sqlite-autoconf-3300100/.libs/libsqlite3.so.0 (0x00007f9979578000)]]></m:pre>
       
    78 		
       
    79 		<p>Now we can use new features like window functions:</p>
       
    80 		
       
    81 		<m:pre jazyk="bash"><![CDATA[relpipe-in-fstab \
       
    82 	| relpipe-tr-sql \
       
    83 		--relation "fs_types" "
       
    84 			SELECT 
       
    85 				mount_point, 
       
    86 				type, 
       
    87 				count(*) OVER (PARTITION BY type) AS same_type_count 
       
    88 			FROM fstab" \
       
    89 	| relpipe-out-tabular]]></m:pre>
       
    90 	
       
    91 		<p>And get result like this one:</p>
       
    92 		<m:pre jazyk="text"><![CDATA[fstab:
       
    93  ╭──────────────────────┬───────────────┬──────────────────────────╮
       
    94  │ mount_point (string) │ type (string) │ same_type_count (string) │
       
    95  ├──────────────────────┼───────────────┼──────────────────────────┤
       
    96  │ /home                │ btrfs         │ 1                        │
       
    97  │ /                    │ ext4          │ 2                        │
       
    98  │ /mnt/data            │ ext4          │ 2                        │
       
    99  │ /media/cdrom0        │ udf,iso9660   │ 1                        │
       
   100  │ /mnt/private         │ xfs           │ 1                        │
       
   101  ╰──────────────────────┴───────────────┴──────────────────────────╯
       
   102 Record count: 5]]></m:pre>
       
   103 		
       
   104 		
       
   105 		<p>That would not be possible with older versions of the SQLite library – as we can check by unsetting the <code>LD_PRELOAD</code> variable:</p>
       
   106 		<m:pre jazyk="bash"><![CDATA[unset LD_PRELOAD]]></m:pre>
       
   107 		<p>Which returns us to the previous state where SQLite from our distribution was used. And the calling the same SQL query leads to an error.</p>
       
   108 		
       
   109 		<p>
       
   110 			The <code>LD_PRELOAD</code> hack can be used with any other software – it is not specific to <m:name/>.
       
   111 			Another example is the <a href="https://mouse.globalcode.info/v_0/spacenav-hack.xhtml">Spacenav Hack</a>  which bridges/translates two APIs of a library.
       
   112 		</p>
       
   113 
       
   114 				
       
   115 		<h2>ABI compatibility</h2>
       
   116 		
       
   117 		<p>
       
   118 			The prerequisite for such easy library swapping is the compatibility of the ABI (application binary interface).
       
   119 			It means that we can change the library internals (the SQL language features in this case) but we must retain the compiled representation of the C functions compatible
       
   120 			so the both parts (the library and the program) will still fit together. We can not e.g. remove a C function.
       
   121 			And we should also not do any incompatible changes on the semantic level (although it could still link together, it would lead to unwanted results).
       
   122 		</p>
       
   123 		
       
   124 		<p>
       
   125 			In case of libraries that follow the <a href="https://semver.org/">Semantic versioning</a> (as required by <a href="https://sane-software.globalcode.info/">Sane software manifesto</a>) for their ABI,
       
   126 			it is easy to say which versions are compatible and which would require recompiling the program or even changing its source code.
       
   127 			If the <em>patch</em> or <em>minor</em> version numbers were changed, the libraries could be swapped this way.
       
   128 			If the <em>major</em> version was changed, it would be probably necessary to also modify the software that uses this library.
       
   129 		</p>
       
   130 		
       
   131 	</text>
       
   132 
       
   133 </stránka>