summaryrefslogtreecommitdiffstats
path: root/www/session/sqlite3session_attach.html
blob: 0670df78c42de7b10fdd4f7939676147d1acd738 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
<!DOCTYPE html>
<html><head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link href="../sqlite.css" rel="stylesheet">
<title>Attach A Table To A Session Object</title>
<!-- path=../ -->
</head>
<body>
<div class=nosearch>
<a href="../index.html">
<img class="logo" src="../images/sqlite370_banner.gif" alt="SQLite" border="0">
</a>
<div><!-- IE hack to prevent disappearing logo --></div>
<div class="tagline desktoponly">
Small. Fast. Reliable.<br>Choose any three.
</div>
<div class="menu mainmenu">
<ul>
<li><a href="../index.html">Home</a>
<li class='mobileonly'><a href="javascript:void(0)" onclick='toggle_div("submenu")'>Menu</a>
<li class='wideonly'><a href='../about.html'>About</a>
<li class='desktoponly'><a href="../docs.html">Documentation</a>
<li class='desktoponly'><a href="../download.html">Download</a>
<li class='wideonly'><a href='../copyright.html'>License</a>
<li class='desktoponly'><a href="../support.html">Support</a>
<li class='desktoponly'><a href="../prosupport.html">Purchase</a>
<li class='search' id='search_menubutton'>
<a href="javascript:void(0)" onclick='toggle_search()'>Search</a>
</ul>
</div>
<div class="menu submenu" id="submenu">
<ul>
<li><a href='../about.html'>About</a>
<li><a href='../docs.html'>Documentation</a>
<li><a href='../download.html'>Download</a>
<li><a href='../support.html'>Support</a>
<li><a href='../prosupport.html'>Purchase</a>
</ul>
</div>
<div class="searchmenu" id="searchmenu">
<form method="GET" action="../search">
<select name="s" id="searchtype">
<option value="d">Search Documentation</option>
<option value="c">Search Changelog</option>
</select>
<input type="text" name="q" id="searchbox" value="">
<input type="submit" value="Go">
</form>
</div>
</div>
<script>
function toggle_div(nm) {
var w = document.getElementById(nm);
if( w.style.display=="block" ){
w.style.display = "none";
}else{
w.style.display = "block";
}
}
function toggle_search() {
var w = document.getElementById("searchmenu");
if( w.style.display=="block" ){
w.style.display = "none";
} else {
w.style.display = "block";
setTimeout(function(){
document.getElementById("searchbox").focus()
}, 30);
}
}
function div_off(nm){document.getElementById(nm).style.display="none";}
window.onbeforeunload = function(e){div_off("submenu");}
/* Disable the Search feature if we are not operating from CGI, since */
/* Search is accomplished using CGI and will not work without it. */
if( !location.origin || !location.origin.match || !location.origin.match(/http/) ){
document.getElementById("search_menubutton").style.display = "none";
}
/* Used by the Hide/Show button beside syntax diagrams, to toggle the */
function hideorshow(btn,obj){
var x = document.getElementById(obj);
var b = document.getElementById(btn);
if( x.style.display!='none' ){
x.style.display = 'none';
b.innerHTML='show';
}else{
x.style.display = '';
b.innerHTML='hide';
}
return false;
}
var antiRobot = 0;
function antiRobotGo(){
if( antiRobot!=3 ) return;
antiRobot = 7;
var j = document.getElementById("mtimelink");
if(j && j.hasAttribute("data-href")) j.href=j.getAttribute("data-href");
}
function antiRobotDefense(){
document.body.onmousedown=function(){
antiRobot |= 2;
antiRobotGo();
document.body.onmousedown=null;
}
document.body.onmousemove=function(){
antiRobot |= 2;
antiRobotGo();
document.body.onmousemove=null;
}
setTimeout(function(){
antiRobot |= 1;
antiRobotGo();
}, 100)
antiRobotGo();
}
antiRobotDefense();
</script>
<a href="../session/intro.html"><h2>Session Module C Interface</h2></a><h2>Attach A Table To A Session Object</h2><blockquote><pre>int sqlite3session_attach(
  sqlite3_session *pSession,      /* Session object */
  const char *zTab                /* Table name */
);
</pre></blockquote><p>
If argument zTab is not NULL, then it is the name of a table to attach
to the session object passed as the first argument. All subsequent changes 
made to the table while the session object is enabled will be recorded. See 
documentation for <a href="../session/sqlite3session_changeset.html">sqlite3session_changeset()</a> for further details.</p>

<p>Or, if argument zTab is NULL, then changes are recorded for all tables
in the database. If additional tables are added to the database (by 
executing "CREATE TABLE" statements) after this call is made, changes for 
the new tables are also recorded.</p>

<p>Changes can only be recorded for tables that have a PRIMARY KEY explicitly
defined as part of their CREATE TABLE statement. It does not matter if the 
PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY
KEY may consist of a single column, or may be a composite key.</p>

<p>It is not an error if the named table does not exist in the database. Nor
is it an error if the named table does not have a PRIMARY KEY. However,
no changes will be recorded in either of these scenarios.</p>

<p>Changes are not recorded for individual rows that have NULL values stored
in one or more of their PRIMARY KEY columns.</p>

<p>SQLITE_OK is returned if the call completes without error. Or, if an error 
occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.</p>

<p><h3>Special sqlite_stat1 Handling</h3></p>

<p>As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to 
some of the rules above. In SQLite, the schema of sqlite_stat1 is:
 <pre>
 &nbsp;     CREATE TABLE sqlite_stat1(tbl,idx,stat)  
 </pre></p>

<p>Even though sqlite_stat1 does not have a PRIMARY KEY, changes are 
recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes 
are recorded for rows for which (idx IS NULL) is true. However, for such
rows a zero-length blob (SQL value X'') is stored in the changeset or
patchset instead of a NULL value. This allows such changesets to be
manipulated by legacy implementations of sqlite3changeset_invert(),
concat() and similar.</p>

<p>The sqlite3changeset_apply() function automatically converts the 
zero-length blob back to a NULL value when updating the sqlite_stat1
table. However, if the application calls sqlite3changeset_new(),
sqlite3changeset_old() or sqlite3changeset_conflict on a changeset 
iterator directly (including on a changeset iterator passed to a
conflict-handler callback) then the X'' value is returned. The application
must translate X'' to NULL itself if required.</p>

<p>Legacy (older than 3.22.0) versions of the sessions module cannot capture
changes made to the sqlite_stat1 table. Legacy versions of the
sqlite3changeset_apply() function silently ignore any modifications to the
sqlite_stat1 table that are part of a changeset or patchset.
</p><p>See also lists of
  <a href="../session/objlist.html">Objects</a>,
  <a href="../session/constlist.html">Constants</a>, and
  <a href="../session/funclist.html">Functions</a>.</p>