Check-in [70bf1f87e4]

Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
SHA1 Hash:70bf1f87e4f7b0d6083c39e7bb0a49203f8ea3e7
Date: 2008-11-13 17:28:33
User: stephan
Comment:fixed missing-children bug in sql reader (required an extra alloc, though :()
Changes
hide diffs unified diffs patch

Changes to src/c11n_io_handler_sql.c

Old (47c8a0b6690ef747) New (8d436283c0bcbe1c)
1 #include <stdlib.h> /* malloc()/free() */ 1 #include <stdlib.h> /* malloc()/free() */
2 #include <sqlite3.h> 2 #include <sqlite3.h>
3 #include <assert.h> 3 #include <assert.h>
4 #include "s11n.net/c11n/io/c11n_io_handler_sql.h" 4 #include "s11n.net/c11n/io/c11n_io_handler_sql.h"
5 #include "s11n.net/c11n/io/c11n_stream_whclob.h" 5 #include "s11n.net/c11n/io/c11n_stream_whclob.h"
86 hidden lines
92 while( SQLITE_ROW == rc ) 92 while( SQLITE_ROW == rc )
93 { 93 {
94 c11n_node * n = c11n_node_create( 0 ); 94 c11n_node * n = c11n_node_create( 0 );
95 if( ! impl->root ) impl->root = n; 95 if( ! impl->root ) impl->root = n;
96 const char * k = (char const *)sqlite3_column_text(stmt,0); 96 const char * k = (char const *)sqlite3_column_text(stmt,0);
> 97 #if 1
97 c11n_node_prop_set( n, ".id", k ); 98 c11n_node_prop_set( n, ".id", k );
98 #if 0 | 99 /* We have to copy this string to avoid lifetime issues - stmt owns k.
99 whhash_insert( impl->ht, c11n_copy_str( k ), n ); /* We have to copy this string to avoid lifetime issues - stmt owns k. */ | 100 In theory we could use the value from c11n_node_prop_get(n,".id",&k),
| 101 but when i do so the address of k is stored in the hashtable, which
| 102 isn't useful because it's the same on each loop iteration.
| 103 */
| 104 whhash_insert( impl->ht, c11n_copy_str( k ), n );
100 #else 105 #else
101 c11n_node_prop_get( n, ".id", &k ); 106 c11n_node_prop_get( n, ".id", &k );
102 whhash_insert( impl->ht, (char /*i fucking hate this cast*/ *)k, n ); /* c11n_node_prop_get() copies k, so we can use that copy as a key. */ 107 whhash_insert( impl->ht, (char /*i fucking hate this cast*/ *)k, n ); /* c11n_node_prop_get() copies k, so we can use that copy as a key. */
103 #endif 108 #endif
> 109 //MARKER("Added .id [%s] = node@%p\n", k, whhash_search(impl->ht,k) );
104 k = (char const *) sqlite3_column_text(stmt,1); 110 k = (char const *) sqlite3_column_text(stmt,1);
105 c11n_node_prop_set( n, ".pid", k ); 111 c11n_node_prop_set( n, ".pid", k );
106 k = (char const *) sqlite3_column_text(stmt,2); 112 k = (char const *) sqlite3_column_text(stmt,2);
107 c11n_node_set_name( n, k ); 113 c11n_node_set_name( n, k );
108 k = (char const *) sqlite3_column_text(stmt,3); 114 k = (char const *) sqlite3_column_text(stmt,3);
109 c11n_node_set_class( n, k ); 115 c11n_node_set_class( n, k );
110 rc = sqlite3_step(stmt); 116 rc = sqlite3_step(stmt);
111 } 117 }
112 sqlite3_finalize(stmt); 118 sqlite3_finalize(stmt);
113 if( (SQLITE_DONE != rc) && (SQLITE_OK != rc) ) return false; | 119 if( (SQLITE_DONE != rc) && (SQLITE_OK != rc) )
114 //MARKER("root = @%p. Hashed %u entries.\n",impl->root,whhash_count(impl->ht)); | 120 {
| 121 C11N_LOG(C11N_LOG_IO_ERR)("FIXME: loading of nodes from SQL failed at a bad point. We're probably leaking nodes here!");
| 122 return false;
| 123 }
| 124 //MARKER("root = @%p. Hashed %u entries.\n",(void const *)impl->root,whhash_count(impl->ht));
115 whhash_iter * hit = whhash_get_iter(impl->ht); 125 whhash_iter * hit = whhash_get_iter(impl->ht);
116 if( ! hit ) return false; 126 if( ! hit ) return false;
117 bool isokay = true; 127 bool isokay = true;
118 do 128 do
119 { 129 {
2 hidden lines
122 char const * key = 0; 132 char const * key = 0;
123 c11n_node_prop_get( aN, ".pid", &key ); 133 c11n_node_prop_get( aN, ".pid", &key );
124 assert( key && "got an empty .pid!"); 134 assert( key && "got an empty .pid!");
125 //MARKER("aN.pid=[%s]\n", key ); 135 //MARKER("aN.pid=[%s]\n", key );
126 c11n_node * aP = (c11n_node *)whhash_search( impl->ht, key ); 136 c11n_node * aP = (c11n_node *)whhash_search( impl->ht, key );
127 //MARKER("node#%s p=%p aN.pid=#%s\n", (char const *)whhash_iter_key(hit), aP, key ); | 137 //MARKER("node#%s parent=%p aN.pid=#%s\n", (char const *)whhash_iter_key(hit), (void const *)aP, key );
128 size_t NID = 0; 138 size_t NID = 0;
129 c11n_node_prop_get_fe( aN, ".id", "%lu", &NID ); 139 c11n_node_prop_get_fe( aN, ".id", "%lu", &NID );
130 c11n_node_prop_unset( aN, ".id" ); 140 c11n_node_prop_unset( aN, ".id" );
131 c11n_node_prop_unset( aN, ".pid" ); 141 c11n_node_prop_unset( aN, ".pid" );
132 if( aP ) 142 if( aP )
95 hidden lines
228 "DROP INDEX IF EXISTS ndx_nodes;\n" 238 "DROP INDEX IF EXISTS ndx_nodes;\n"
229 "DROP INDEX IF EXISTS ndx_props;\n" 239 "DROP INDEX IF EXISTS ndx_props;\n"
230 "DROP TABLE IF EXISTS n;\n" 240 "DROP TABLE IF EXISTS n;\n"
231 "DROP TABLE IF EXISTS p;\n" 241 "DROP TABLE IF EXISTS p;\n"
232 "\n" 242 "\n"
233 "CREATE TABLE n -- c11n_node trees\n" | 243 "CREATE TABLE n -- c11n_node tree\n"
234 "(\n" 244 "(\n"
235 " id INTEGER PRIMARY KEY AUTOINCREMENT,\n" 245 " id INTEGER PRIMARY KEY AUTOINCREMENT,\n"
236 " pid INTEGER REFERENCES n(id),\n" 246 " pid INTEGER REFERENCES n(id),\n"
237 " name TEXT,\n" 247 " name TEXT,\n"
238 " class TEXT\n" 248 " class TEXT\n"
30 hidden lines
269 } 279 }
270 static bool c11n_io_handler_sql_save_one_node( c11n_io_handler * self, 280 static bool c11n_io_handler_sql_save_one_node( c11n_io_handler * self,
271 c11n_node const * src, 281 c11n_node const * src,
272 c11n_stream * dest ) 282 c11n_stream * dest )
273 { 283 {
274 #define PUL(X) ((unsigned int)(X)) | 284 #define PUL(X) ((unsigned long)(X))
275 c11n_node const * par = c11n_node_parent_c( src ); 285 c11n_node const * par = c11n_node_parent_c( src );
> 286 /**
> 287 Maybe todo: replace the %Q writef specifiers with
> 288 c11n_io_escape_string(). %Q is an extension of vappendf(),
> 289 inherited from the sqlite3 origins of vappendf()'s
> 290 implementation.
> 291 */
276 c11n_stream_writef( dest, 292 c11n_stream_writef( dest,
277 "INSERT INTO n (id,pid,name,class) " 293 "INSERT INTO n (id,pid,name,class) "
278 "VALUES (%u,%u,%Q,%Q);\n", 294 "VALUES (%u,%u,%Q,%Q);\n",
279 PUL(src), 295 PUL(src),
280 PUL((par?par:0)), 296 PUL((par?par:0)),
10 hidden lines
291 c11n_prop_iter_key( &piter ), 307 c11n_prop_iter_key( &piter ),
292 c11n_prop_iter_val( &piter ) ); 308 c11n_prop_iter_val( &piter ) );
293 if( ! rc ) return false; 309 if( ! rc ) return false;
294 c11n_prop_iter_next(&piter); 310 c11n_prop_iter_next(&piter);
295 } 311 }
296 #undef PUL | 312 #undef PUL /* i sometimes find it interesting that even though macros do not respect scope, we programmers tend to respect it when defining/undefining macros. */
297 c11n_node_iter_c chi = c11n_node_children_iter_c( src ); 313 c11n_node_iter_c chi = c11n_node_children_iter_c( src );
298 while( c11n_node_iter_isvalid_c( &chi ) ) 314 while( c11n_node_iter_isvalid_c( &chi ) )
299 { 315 {
300 if( ! c11n_io_handler_sql_save_one_node( self, chi.node, dest ) ) return false; 316 if( ! c11n_io_handler_sql_save_one_node( self, chi.node, dest ) ) return false;
301 c11n_node_iter_next_c(&chi); 317 c11n_node_iter_next_c(&chi);
302 } 318 }
303 319
304 return true; 320 return true;
305 } 321 }
> 322
306 /** 323 /**
307 Implementation of c11n_io_handler::save_node() for c11n_io_handler_sql. 324 Implementation of c11n_io_handler::save_node() for c11n_io_handler_sql.
308 */ 325 */
309 static bool c11n_io_handler_sql_save_root_node( c11n_io_handler * self, 326 static bool c11n_io_handler_sql_save_root_node( c11n_io_handler * self,
310 c11n_node const * src, 327 c11n_node const * src,
79 hidden lines
390 meta->ht = whhash_create(17, 407 meta->ht = whhash_create(17,
391 whhash_hash_cstring_djb2m, 408 whhash_hash_cstring_djb2m,
392 whhash_cmp_cstring ); 409 whhash_cmp_cstring );
393 if( meta->ht ) 410 if( meta->ht )
394 { 411 {
395 //whhash_set_dtors( meta->ht, free, 0 ); | 412 whhash_set_dtors( meta->ht, free, 0 );
396 st->implData = meta; 413 st->implData = meta;
397 } 414 }
398 else 415 else
399 { 416 {
400 st->api->destroy(st); 417 st->api->destroy(st);
17 hidden lines
418 435
419 c11n_io_handler * c11n_io_handler_factory_sql( c11n_const_string_t ignored ) 436 c11n_io_handler * c11n_io_handler_factory_sql( c11n_const_string_t ignored )
420 { 437 {
421 return c11n_io_handler_sql_new(); 438 return c11n_io_handler_sql_new();
422 } 439 }