KRecipes – cooking recipes manager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1035 lines
40KB

  1. /***************************************************************************
  2. * Copyright (C) 2003-2004 by *
  3. * Unai Garro (ugarro@users.sourceforge.net) *
  4. * Jason Kivlighn (jkivlighn@gmail.com) *
  5. * Cyril Bosselut (bosselut@b1project.com) *
  6. * *
  7. * Copyright (C) 2006 Jason Kivlighn (jkivlighn@gmail.com) *
  8. * *
  9. * This program is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. ***************************************************************************/
  14. #include "literecipedb.h"
  15. #include <ntqbuffer.h>
  16. #include <kdebug.h>
  17. #include <tdeconfig.h>
  18. #include <tdeglobal.h>
  19. #include <tdelocale.h>
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #if HAVE_SQLITE3
  24. #include <sqlite3.h>
  25. #elif HAVE_SQLITE
  26. #include <sqlite.h>
  27. #endif
  28. //keep these two around for porting old databases
  29. int sqlite_decode_binary( const unsigned char *in, unsigned char *out );
  30. TQString escape( const TQString &s );
  31. LiteRecipeDB::LiteRecipeDB( const TQString &_dbFile ) : TQSqlRecipeDB( TQString::null, TQString::null, TQString::null, _dbFile )
  32. {
  33. /* TDEConfig * config = TDEGlobal::config();
  34. config->setGroup( "Server" );
  35. if ( dbFile.isNull() )
  36. dbFile = config->readEntry( "DBFile", locateLocal ( "appdata", DB_FILENAME ) );
  37. */
  38. }
  39. LiteRecipeDB::~LiteRecipeDB()
  40. {
  41. }
  42. int LiteRecipeDB::lastInsertID()
  43. {
  44. int lastID = -1;
  45. TQSqlQuery query("SELECT lastInsertID()",database);
  46. if ( query.isActive() && query.first() )
  47. lastID = query.value(0).toInt();
  48. //kdDebug()<<"lastInsertID(): "<<lastID<<endl;
  49. return lastID;
  50. }
  51. TQStringList LiteRecipeDB::backupCommand() const
  52. {
  53. #if HAVE_SQLITE
  54. TQString binary = "sqlite";
  55. #elif HAVE_SQLITE3
  56. TQString binary = "sqlite3";
  57. #endif
  58. TDEConfig * config = TDEGlobal::config();
  59. config->setGroup( "Server" );
  60. binary = config->readEntry( "SQLitePath", binary );
  61. TQStringList command;
  62. command<<binary<<database->databaseName()<<".dump";
  63. return command;
  64. }
  65. TQStringList LiteRecipeDB::restoreCommand() const
  66. {
  67. #if HAVE_SQLITE
  68. TQString binary = "sqlite";
  69. #elif HAVE_SQLITE3
  70. TQString binary = "sqlite3";
  71. #endif
  72. TDEConfig * config = TDEGlobal::config();
  73. config->setGroup( "Server" );
  74. binary = config->readEntry( "SQLitePath", binary );
  75. TQStringList command;
  76. command<<binary<<database->databaseName();
  77. return command;
  78. }
  79. void LiteRecipeDB::createDB()
  80. {
  81. //The file is created by SQLite automatically
  82. }
  83. void LiteRecipeDB::createTable( const TQString &tableName )
  84. {
  85. TQStringList commands;
  86. if ( tableName == "recipes" )
  87. commands << TQString( "CREATE TABLE recipes (id INTEGER NOT NULL,title VARCHAR(%1), yield_amount FLOAT, yield_amount_offset FLOAT, yield_type_id INTEGER DEFAULT '-1', instructions TEXT, photo BLOB, prep_time TIME, ctime TIMESTAMP, mtime TIMESTAMP, atime TIMESTAMP, PRIMARY KEY (id));" ).arg( maxRecipeTitleLength() );
  88. else if ( tableName == "ingredients" )
  89. commands << TQString( "CREATE TABLE ingredients (id INTEGER NOT NULL, name VARCHAR(%1), PRIMARY KEY (id));" ).arg( maxIngredientNameLength() );
  90. else if ( tableName == "ingredient_list" ) {
  91. commands << "CREATE TABLE ingredient_list (id INTEGER NOT NULL, recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, amount_offset FLOAT, unit_id INTEGER, order_index INTEGER, group_id INTEGER, substitute_for INTEGER, PRIMARY KEY(id) );"
  92. << "CREATE index ridil_index ON ingredient_list(recipe_id);"
  93. << "CREATE index iidil_index ON ingredient_list(ingredient_id);"
  94. << "CREATE index gidil_index ON ingredient_list(group_id);";
  95. }
  96. else if ( tableName == "unit_list" )
  97. commands << "CREATE TABLE unit_list (ingredient_id INTEGER, unit_id INTEGER);";
  98. else if ( tableName == "units" )
  99. commands << TQString( "CREATE TABLE units (id INTEGER NOT NULL, name VARCHAR(%1), name_abbrev VARCHAR(%2), plural VARCHAR(%3), plural_abbrev VARCHAR(%4), type INTEGER NOT NULL DEFAULT '0',PRIMARY KEY (id));" )
  100. .arg( maxUnitNameLength() ).arg( maxUnitNameLength() ).arg( maxUnitNameLength() ).arg( maxUnitNameLength() );
  101. else if ( tableName == "prep_methods" )
  102. commands << TQString( "CREATE TABLE prep_methods (id INTEGER NOT NULL, name VARCHAR(%1), PRIMARY KEY (id));" ).arg( maxPrepMethodNameLength() );
  103. else if ( tableName == "prep_method_list" ) {
  104. commands << "CREATE TABLE prep_method_list (ingredient_list_id INTEGER NOT NULL,prep_method_id INTEGER NOT NULL, order_index INTEGER );"
  105. << "CREATE index iid_index ON prep_method_list(ingredient_list_id);"
  106. << "CREATE index pid_index ON prep_method_list(prep_method_id);";
  107. }
  108. else if ( tableName == "ingredient_info" )
  109. commands << "CREATE TABLE ingredient_info (ingredient_id INTEGER, property_id INTEGER, amount FLOAT, per_units INTEGER);";
  110. else if ( tableName == "ingredient_properties" )
  111. commands << "CREATE TABLE ingredient_properties (id INTEGER NOT NULL,name VARCHAR(20), units VARCHAR(20), PRIMARY KEY (id));";
  112. else if ( tableName == "ingredient_weights" ) {
  113. commands << "CREATE TABLE ingredient_weights (id INTEGER NOT NULL, ingredient_id INTEGER NOT NULL, amount FLOAT, unit_id INTEGER, weight FLOAT, weight_unit_id INTEGER, prep_method_id INTEGER, PRIMARY KEY (id) );"
  114. << "CREATE index weight_wid_index ON ingredient_weights(weight_unit_id)"
  115. << "CREATE index weight_pid_index ON ingredient_weights(prep_method_id)"
  116. << "CREATE index weight_uid_index ON ingredient_weights(unit_id)"
  117. << "CREATE index weight_iid_index ON ingredient_weights(ingredient_id)";
  118. }
  119. else if ( tableName == "units_conversion" )
  120. commands << "CREATE TABLE units_conversion (unit1_id INTEGER, unit2_id INTEGER, ratio FLOAT);";
  121. else if ( tableName == "categories" ) {
  122. commands << TQString( "CREATE TABLE categories (id INTEGER NOT NULL, name varchar(%1) default NULL, parent_id INGEGER NOT NULL default -1, PRIMARY KEY (id));" ).arg( maxCategoryNameLength() );
  123. commands << "CREATE index parent_id_index ON categories(parent_id);";
  124. }
  125. else if ( tableName == "category_list" ) {
  126. commands << "CREATE TABLE category_list (recipe_id INTEGER NOT NULL,category_id INTEGER NOT NULL);"
  127. << "CREATE index rid_index ON category_list(recipe_id);"
  128. << "CREATE index cid_index ON category_list(category_id);";
  129. }
  130. else if ( tableName == "authors" )
  131. commands << TQString( "CREATE TABLE authors (id INTEGER NOT NULL, name varchar(%1) default NULL,PRIMARY KEY (id));" ).arg( maxAuthorNameLength() );
  132. else if ( tableName == "author_list" )
  133. commands << "CREATE TABLE author_list (recipe_id INTEGER NOT NULL,author_id INTEGER NOT NULL);";
  134. else if ( tableName == "db_info" ) {
  135. commands << "CREATE TABLE db_info (ver FLOAT NOT NULL,generated_by varchar(200) default NULL);";
  136. commands << TQString( "INSERT INTO db_info VALUES(%1,'Krecipes %2');" ).arg( latestDBVersion() ).arg( krecipes_version() );
  137. }
  138. else if ( tableName == "ingredient_groups" ) {
  139. commands << TQString( "CREATE TABLE ingredient_groups (id INTEGER NOT NULL, name varchar(%1), PRIMARY KEY (id));" ).arg( maxIngGroupNameLength() );
  140. }
  141. else if ( tableName == "yield_types" ) {
  142. commands << TQString( "CREATE TABLE yield_types (id INTEGER NOT NULL, name varchar(%1), PRIMARY KEY (id));" ).arg( maxYieldTypeLength() );
  143. }
  144. else if ( tableName == "ratings" )
  145. commands << "CREATE TABLE ratings (id INTEGER NOT NULL, recipe_id int(11) NOT NULL, comment TEXT, rater TEXT, created TIMESTAMP, PRIMARY KEY (id));";
  146. else if ( tableName == "rating_criteria" )
  147. commands << "CREATE TABLE rating_criteria (id INTEGER NOT NULL, name TEXT, PRIMARY KEY (id));";
  148. else if ( tableName == "rating_criterion_list" )
  149. commands << "CREATE TABLE rating_criterion_list (rating_id INTEGER NOT NULL, rating_criterion_id INTEGER, stars FLOAT);";
  150. else
  151. return ;
  152. // execute the queries
  153. for ( TQStringList::const_iterator it = commands.begin(); it != commands.end(); ++it )
  154. database->exec( *it );
  155. }
  156. void LiteRecipeDB::portOldDatabases( float version )
  157. {
  158. TQString command;
  159. if ( tqRound(version*10) < 5 ) {
  160. //===========add prep_method_id to ingredient_list table
  161. //There's no ALTER command in SQLite, so we have to copy all data to a new table and then recreate the table with the prep_method_id
  162. database->exec( "CREATE TABLE ingredient_list_copy (recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, unit_id INTEGER, order_index INTEGER);" );
  163. TQSqlQuery copyQuery( "SELECT recipe_id,ingredient_id,amount,unit_id,order_index FROM ingredient_list;", database );
  164. if ( copyQuery.isActive() ) {
  165. while ( copyQuery.next() ) {
  166. command = TQString( "INSERT INTO ingredient_list_copy VALUES(%1,%2,%3,%4,%5);" )
  167. .arg( copyQuery.value( 0 ).toInt() )
  168. .arg( copyQuery.value( 1 ).toInt() )
  169. .arg( copyQuery.value( 2 ).toDouble() )
  170. .arg( copyQuery.value( 3 ).toInt() )
  171. .arg( copyQuery.value( 4 ).toInt() );
  172. database->exec( command );
  173. emit progress();
  174. }
  175. }
  176. database->exec( "DROP TABLE ingredient_list" );
  177. database->exec( "CREATE TABLE ingredient_list (recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, unit_id INTEGER, prep_method_id INTEGER, order_index INTEGER);" );
  178. copyQuery = database->exec( "SELECT * FROM ingredient_list_copy" );
  179. if ( copyQuery.isActive() ) {
  180. while ( copyQuery.next() ) {
  181. command = TQString( "INSERT INTO ingredient_list VALUES(%1,%2,%3,%4,%5,%6);" )
  182. .arg( copyQuery.value( 0 ).toInt() )
  183. .arg( copyQuery.value( 1 ).toInt() )
  184. .arg( copyQuery.value( 2 ).toDouble() )
  185. .arg( copyQuery.value( 3 ).toInt() )
  186. .arg( -1 ) //default prep method
  187. .arg( copyQuery.value( 4 ).toInt() );
  188. database->exec( command );
  189. emit progress();
  190. }
  191. }
  192. database->exec( "DROP TABLE ingredient_list_copy" );
  193. database->exec( "CREATE index ridil_index ON ingredient_list(recipe_id);" );
  194. database->exec( "CREATE index iidil_index ON ingredient_list(ingredient_id);" );
  195. //==============expand length of author name to 50 characters
  196. database->exec( "CREATE TABLE authors_copy (id INTEGER, name varchar(20));" );
  197. copyQuery = database->exec( "SELECT * FROM authors;" );
  198. if ( copyQuery.isActive() ) {
  199. while ( copyQuery.next() ) {
  200. command = TQString( "INSERT INTO authors_copy VALUES(%1,'%2');" )
  201. .arg( copyQuery.value( 0 ).toInt() )
  202. .arg( escape( copyQuery.value( 1 ).toString() ) );
  203. database->exec( command );
  204. emit progress();
  205. }
  206. }
  207. database->exec( "DROP TABLE authors" );
  208. database->exec( "CREATE TABLE authors (id INTEGER NOT NULL, name varchar(50) default NULL,PRIMARY KEY (id));" );
  209. copyQuery = database->exec( "SELECT * FROM authors_copy" );
  210. if ( copyQuery.isActive() ) {
  211. while ( copyQuery.next() ) {
  212. command = TQString( "INSERT INTO authors VALUES(%1,'%2');" )
  213. .arg( copyQuery.value( 0 ).toInt() )
  214. .arg( escape( copyQuery.value( 1 ).toString() ) );
  215. database->exec( command );
  216. emit progress();
  217. }
  218. }
  219. database->exec( "DROP TABLE authors_copy" );
  220. //==================expand length of category name to 40 characters
  221. database->exec( "CREATE TABLE categories_copy (id INTEGER, name varchar(20));" );
  222. copyQuery = database->exec( "SELECT * FROM categories;" );
  223. if ( copyQuery.isActive() ) {
  224. while ( copyQuery.next() ) {
  225. command = TQString( "INSERT INTO categories_copy VALUES(%1,'%2');" )
  226. .arg( copyQuery.value( 0 ).toInt() )
  227. .arg( escape( copyQuery.value( 1 ).toString() ) );
  228. database->exec( command );
  229. emit progress();
  230. }
  231. }
  232. database->exec( "DROP TABLE categories" );
  233. database->exec( "CREATE TABLE categories (id INTEGER NOT NULL, name varchar(40) default NULL,PRIMARY KEY (id));" );
  234. copyQuery = database->exec( "SELECT * FROM categories_copy" );
  235. if ( copyQuery.isActive() ) {
  236. while ( copyQuery.next() ) {
  237. command = TQString( "INSERT INTO categories VALUES(%1,'%2');" )
  238. .arg( copyQuery.value( 0 ).toInt() )
  239. .arg( escape( copyQuery.value( 1 ).toString() ) );
  240. database->exec( command );
  241. emit progress();
  242. }
  243. }
  244. database->exec( "DROP TABLE categories_copy" );
  245. //================Set the version to the new one (0.5)
  246. command = "DELETE FROM db_info;"; // Remove previous version records if they exist
  247. database->exec( command );
  248. command = "INSERT INTO db_info VALUES(0.5,'Krecipes 0.5');";
  249. database->exec( command );
  250. }
  251. if ( tqRound(version*10) < 6 ) {
  252. //==================add a column to 'categories' to allow subcategories
  253. database->exec( "CREATE TABLE categories_copy (id INTEGER, name varchar(40));" );
  254. TQSqlQuery copyQuery = database->exec( "SELECT * FROM categories;" );
  255. if ( copyQuery.isActive() ) {
  256. while ( copyQuery.next() ) {
  257. command = TQString( "INSERT INTO categories_copy VALUES(%1,'%2');" )
  258. .arg( copyQuery.value( 0 ).toInt() )
  259. .arg( escape( copyQuery.value( 1 ).toString() ) );
  260. database->exec( command );
  261. emit progress();
  262. }
  263. }
  264. database->exec( "DROP TABLE categories" );
  265. database->exec( "CREATE TABLE categories (id INTEGER NOT NULL, name varchar(40) default NULL, parent_id INTEGER NOT NULL, PRIMARY KEY (id));" );
  266. copyQuery = database->exec( "SELECT * FROM categories_copy" );
  267. if ( copyQuery.isActive() ) {
  268. while ( copyQuery.next() ) {
  269. command = TQString( "INSERT INTO categories VALUES(%1,'%2',-1);" )
  270. .arg( copyQuery.value( 0 ).toInt() )
  271. .arg( escape( copyQuery.value( 1 ).toString() ) );
  272. database->exec( command );
  273. emit progress();
  274. }
  275. }
  276. database->exec( "DROP TABLE categories_copy" );
  277. //================Set the version to the new one (0.6)
  278. command = "DELETE FROM db_info;"; // Remove previous version records if they exist
  279. database->exec( command );
  280. command = "INSERT INTO db_info VALUES(0.6,'Krecipes 0.6');";
  281. database->exec( command );
  282. }
  283. if ( tqRound(version*100) < 61 ) {
  284. //==================add a column to 'recipes' to allow prep time
  285. database->exec( "CREATE TABLE recipes_copy (id INTEGER NOT NULL,title VARCHAR(200),persons INTEGER,instructions TEXT, photo BLOB, PRIMARY KEY (id));" );
  286. TQSqlQuery copyQuery = database->exec( "SELECT * FROM recipes;" );
  287. if ( copyQuery.isActive() ) {
  288. while ( copyQuery.next() ) {
  289. command = TQString( "INSERT INTO recipes_copy VALUES(%1,'%2','%3','%4','%5');" )
  290. .arg( escape( copyQuery.value( 0 ).toString() ) )
  291. .arg( escape( copyQuery.value( 1 ).toString() ) )
  292. .arg( escape( copyQuery.value( 2 ).toString() ) )
  293. .arg( escape( copyQuery.value( 3 ).toString() ) )
  294. .arg( escape( copyQuery.value( 4 ).toString() ) );
  295. database->exec( command );
  296. emit progress();
  297. }
  298. }
  299. database->exec( "DROP TABLE recipes" );
  300. database->exec( "CREATE TABLE recipes (id INTEGER NOT NULL,title VARCHAR(200),persons INTEGER,instructions TEXT, photo BLOB, prep_time TIME, PRIMARY KEY (id));" );
  301. copyQuery = database->exec( "SELECT * FROM recipes_copy" );
  302. if ( copyQuery.isActive() ) {
  303. while ( copyQuery.next() ) {
  304. command = TQString( "INSERT INTO recipes VALUES(%1,'%2','%3','%4','%5',NULL);" )
  305. .arg( escape( copyQuery.value( 0 ).toString() ) )
  306. .arg( escape( copyQuery.value( 1 ).toString() ) )
  307. .arg( escape( copyQuery.value( 2 ).toString() ) )
  308. .arg( escape( copyQuery.value( 3 ).toString() ) )
  309. .arg( escape( copyQuery.value( 4 ).toString() ) );
  310. database->exec( command );
  311. emit progress();
  312. }
  313. }
  314. database->exec( "DROP TABLE recipes_copy" );
  315. //================Set the version to the new one (0.61)
  316. command = "DELETE FROM db_info;"; // Remove previous version records if they exist
  317. database->exec( command );
  318. command = "INSERT INTO db_info VALUES(0.61,'Krecipes 0.6');";
  319. database->exec( command );
  320. }
  321. if ( tqRound(version*100) < 62 ) {
  322. database->transaction();
  323. //==================add a column to 'ingredient_list' to allow grouping ingredients
  324. database->exec( "CREATE TABLE ingredient_list_copy (recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, unit_id INTEGER, prep_method_id INTEGER, order_index INTEGER);" );
  325. TQSqlQuery copyQuery = database->exec( "SELECT * FROM ingredient_list;" );
  326. if ( copyQuery.isActive() ) {
  327. while ( copyQuery.next() ) {
  328. command = "INSERT INTO ingredient_list_copy VALUES('" + escape( copyQuery.value( 0 ).toString() )
  329. + "','" + escape( copyQuery.value( 1 ).toString() )
  330. + "','" + escape( copyQuery.value( 2 ).toString() )
  331. + "','" + escape( copyQuery.value( 3 ).toString() )
  332. + "','" + escape( copyQuery.value( 4 ).toString() )
  333. + "','" + escape( copyQuery.value( 5 ).toString() )
  334. + "');";
  335. database->exec( command );
  336. emit progress();
  337. }
  338. }
  339. database->exec( "DROP TABLE ingredient_list" );
  340. database->exec( "CREATE TABLE ingredient_list (recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, unit_id INTEGER, prep_method_id INTEGER, order_index INTEGER, group_id INTEGER);" );
  341. copyQuery = database->exec( "SELECT * FROM ingredient_list_copy" );
  342. if ( copyQuery.isActive() ) {
  343. while ( copyQuery.next() ) {
  344. command = "INSERT INTO ingredient_list VALUES('" + escape( copyQuery.value( 0 ).toString() )
  345. + "','" + escape( copyQuery.value( 1 ).toString() )
  346. + "','" + escape( copyQuery.value( 2 ).toString() )
  347. + "','" + escape( copyQuery.value( 3 ).toString() )
  348. + "','" + escape( copyQuery.value( 4 ).toString() )
  349. + "','" + escape( copyQuery.value( 5 ).toString() )
  350. + "',-1)";
  351. database->exec( command );
  352. emit progress();
  353. }
  354. }
  355. database->exec( "DROP TABLE ingredient_list_copy" );
  356. command = "DELETE FROM db_info;"; // Remove previous version records if they exist
  357. database->exec( command );
  358. command = "INSERT INTO db_info VALUES(0.62,'Krecipes 0.7');";
  359. database->exec( command );
  360. database->commit();
  361. }
  362. if ( tqRound(version*100) < 63 ) {
  363. database->transaction();
  364. //==================add a column to 'units' to allow handling plurals
  365. database->exec( "CREATE TABLE units_copy (id INTEGER NOT NULL, name VARCHAR(20), PRIMARY KEY (id));" );
  366. TQSqlQuery copyQuery = database->exec( "SELECT id,name FROM units;" );
  367. if ( copyQuery.isActive() ) {
  368. while ( copyQuery.next() ) {
  369. command = "INSERT INTO units_copy VALUES('" + escape( copyQuery.value( 0 ).toString() )
  370. + "','" + escape( copyQuery.value( 1 ).toString() )
  371. + "');";
  372. database->exec( command );
  373. emit progress();
  374. }
  375. }
  376. database->exec( "DROP TABLE units" );
  377. database->exec( "CREATE TABLE units (id INTEGER NOT NULL, name VARCHAR(20), plural VARCHAR(20), PRIMARY KEY (id));" );
  378. copyQuery = database->exec( "SELECT id,name FROM units_copy" );
  379. if ( copyQuery.isActive() ) {
  380. while ( copyQuery.next() ) {
  381. command = "INSERT INTO units VALUES('" + escape( copyQuery.value( 0 ).toString() )
  382. + "','" + escape( copyQuery.value( 1 ).toString() )
  383. + "',NULL)";
  384. database->exec( command );
  385. emit progress();
  386. }
  387. }
  388. database->exec( "DROP TABLE units_copy" );
  389. TQSqlQuery result = database->exec( "SELECT id,name FROM units WHERE plural ISNULL;" );
  390. if ( result.isActive() ) {
  391. while ( result.next() ) {
  392. command = "UPDATE units SET plural='" + escape( result.value( 1 ).toString() ) + "' WHERE id=" + TQString::number( result.value( 0 ).toInt() );
  393. database->exec( command );
  394. emit progress();
  395. }
  396. }
  397. command = "DELETE FROM db_info;"; // Remove previous version records if they exist
  398. database->exec( command );
  399. command = "INSERT INTO db_info VALUES(0.63,'Krecipes 0.7');";
  400. database->exec( command );
  401. database->commit();
  402. }
  403. if ( tqRound(version*10) < 7 ) { //simply call 0.63 -> 0.7
  404. database->exec( "UPDATE db_info SET ver='0.7';" );
  405. }
  406. if ( tqRound(version*100) < 81 ) {
  407. database->transaction();
  408. addColumn("CREATE TABLE %1 (recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, %2 unit_id INTEGER, prep_method_id INTEGER, order_index INTEGER, group_id INTEGER)","amount_offset FLOAT","'0'","ingredient_list",3);
  409. //addColumn() doesn't preserve indexes
  410. database->exec("CREATE index ridil_index ON ingredient_list(recipe_id)");
  411. database->exec("CREATE index iidil_index ON ingredient_list(ingredient_id)");
  412. database->exec( "UPDATE db_info SET ver='0.81',generated_by='Krecipes SVN (20050816)';" );
  413. database->commit();
  414. }
  415. if ( tqRound(version*100) < 82 ) {
  416. database->transaction();
  417. //==================add a columns to 'recipes' to allow yield range + yield type
  418. database->exec( "CREATE TABLE recipes_copy (id INTEGER NOT NULL,title VARCHAR(200),persons INTEGER,instructions TEXT, photo BLOB, prep_time TIME, PRIMARY KEY (id));" );
  419. TQSqlQuery copyQuery = database->exec( "SELECT id,title,persons,instructions,photo,prep_time FROM recipes;" );
  420. if ( copyQuery.isActive() ) {
  421. while ( copyQuery.next() ) {
  422. command = "INSERT INTO recipes_copy VALUES('"
  423. + escape( copyQuery.value( 0 ).toString() ) //id
  424. + "','" + escape( copyQuery.value( 1 ).toString() ) //title
  425. + "','" + escape( copyQuery.value( 2 ).toString() ) //persons
  426. + "','" + escape( copyQuery.value( 3 ).toString() ) //instructions
  427. + "','" + escape( copyQuery.value( 4 ).toString() ) //photo
  428. + "','" + escape( copyQuery.value( 5 ).toString() ) //prep_time
  429. + "')";
  430. database->exec( command );
  431. emit progress();
  432. }
  433. }
  434. database->exec( "DROP TABLE recipes" );
  435. database->exec( "CREATE TABLE recipes (id INTEGER NOT NULL,title VARCHAR(200), yield_amount FLOAT, yield_amount_offset FLOAT, yield_type_id INTEGER, instructions TEXT, photo BLOB, prep_time TIME, PRIMARY KEY (id));" );
  436. copyQuery = database->exec( "SELECT id,title,persons,instructions,photo,prep_time FROM recipes_copy" );
  437. if ( copyQuery.isActive() ) {
  438. while ( copyQuery.next() ) {
  439. command = "INSERT INTO recipes VALUES('"
  440. + escape( copyQuery.value( 0 ).toString() ) //id
  441. + "','" + escape( copyQuery.value( 1 ).toString() ) //title
  442. + "','" + escape( copyQuery.value( 2 ).toString() ) //persons, now yield_amount
  443. + "','0" //yield_amount_offset
  444. + "','-1" //yield_type_id
  445. + "','" + escape( copyQuery.value( 3 ).toString() ) //instructions
  446. + "','" + escape( copyQuery.value( 4 ).toString() ) //photo
  447. + "','" + escape( copyQuery.value( 5 ).toString() ) //prep_time
  448. + "')";
  449. database->exec( command );
  450. emit progress();
  451. }
  452. }
  453. database->exec( "DROP TABLE recipes_copy" );
  454. database->exec( "UPDATE db_info SET ver='0.82',generated_by='Krecipes SVN (20050902)';" );
  455. database->commit();
  456. }
  457. if ( tqRound(version*100) < 83 ) {
  458. database->transaction();
  459. //====add a id columns to 'ingredient_list' to identify it for the prep method list
  460. database->exec( "CREATE TABLE ingredient_list_copy (recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, amount_offset FLOAT, unit_id INTEGER, prep_method_id INTEGER, order_index INTEGER, group_id INTEGER);" );
  461. TQSqlQuery copyQuery = database->exec( "SELECT recipe_id,ingredient_id,amount,amount_offset,unit_id,prep_method_id,order_index,group_id FROM ingredient_list" );
  462. if ( copyQuery.isActive() ) {
  463. while ( copyQuery.next() ) {
  464. command = "INSERT INTO ingredient_list_copy VALUES('"
  465. + escape( copyQuery.value( 0 ).toString() )
  466. + "','" + escape( copyQuery.value( 1 ).toString() )
  467. + "','" + escape( copyQuery.value( 2 ).toString() )
  468. + "','" + escape( copyQuery.value( 3 ).toString() )
  469. + "','" + escape( copyQuery.value( 4 ).toString() )
  470. + "','" + escape( copyQuery.value( 5 ).toString() )
  471. + "','" + escape( copyQuery.value( 6 ).toString() )
  472. + "','" + escape( copyQuery.value( 7 ).toString() )
  473. + "')";
  474. database->exec( command );
  475. emit progress();
  476. }
  477. }
  478. database->exec( "DROP TABLE ingredient_list" );
  479. database->exec( "CREATE TABLE ingredient_list (id INTEGER NOT NULL, recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, amount_offset FLOAT, unit_id INTEGER, order_index INTEGER, group_id INTEGER, PRIMARY KEY(id) );" );
  480. copyQuery = database->exec( "SELECT recipe_id,ingredient_id,amount,amount_offset,unit_id,prep_method_id,order_index,group_id FROM ingredient_list_copy" );
  481. if ( copyQuery.isActive() ) {
  482. while ( copyQuery.next() ) {
  483. command = "INSERT INTO ingredient_list VALUES("
  484. + TQString("NULL")
  485. + ",'" + escape( copyQuery.value( 0 ).toString() )
  486. + "','" + escape( copyQuery.value( 1 ).toString() )
  487. + "','" + escape( copyQuery.value( 2 ).toString() )
  488. + "','" + escape( copyQuery.value( 3 ).toString() )
  489. + "','" + escape( copyQuery.value( 4 ).toString() )
  490. + "','" + escape( copyQuery.value( 6 ).toString() )
  491. + "','" + escape( copyQuery.value( 7 ).toString() )
  492. + "')";
  493. database->exec( command );
  494. int prep_method_id = copyQuery.value( 5 ).toInt();
  495. if ( prep_method_id != -1 ) {
  496. command = "INSERT INTO prep_method_list VALUES('"
  497. + TQString::number(lastInsertID())
  498. + "','" + TQString::number(prep_method_id)
  499. + "','1" //order_index
  500. + "')";
  501. database->exec( command );
  502. }
  503. emit progress();
  504. }
  505. }
  506. database->exec( "DROP TABLE ingredient_list_copy" );
  507. database->exec( "CREATE INDEX ridil_index ON ingredient_list(recipe_id);" );
  508. database->exec( "CREATE INDEX iidil_index ON ingredient_list(ingredient_id);" );
  509. database->exec( "UPDATE db_info SET ver='0.83',generated_by='Krecipes SVN (20050909)';" );
  510. database->commit();
  511. }
  512. if ( tqRound(version*100) < 84 ) {
  513. database->transaction();
  514. //==================add a columns to 'recipes' to allow storing atime, mtime, ctime
  515. database->exec( "CREATE TABLE recipes_copy (id INTEGER NOT NULL,title VARCHAR(200), yield_amount FLOAT, yield_amount_offset FLOAT, yield_type_id INTEGER, instructions TEXT, photo BLOB, prep_time TIME, PRIMARY KEY (id));" );
  516. TQSqlQuery copyQuery = database->exec( "SELECT id,title,yield_amount,yield_amount_offset,yield_type_id,instructions,photo,prep_time FROM recipes;" );
  517. if ( copyQuery.isActive() ) {
  518. while ( copyQuery.next() ) {
  519. command = "INSERT INTO recipes_copy VALUES('"
  520. + escape( copyQuery.value( 0 ).toString() )
  521. + "','" + escape( copyQuery.value( 1 ).toString() )
  522. + "','" + escape( copyQuery.value( 2 ).toString() )
  523. + "','" + escape( copyQuery.value( 3 ).toString() )
  524. + "','" + escape( copyQuery.value( 4 ).toString() )
  525. + "','" + escape( copyQuery.value( 5 ).toString() )
  526. + "','" + escape( copyQuery.value( 6 ).toString() )
  527. + "','" + escape( copyQuery.value( 7 ).toString() )
  528. + "')";
  529. database->exec( command );
  530. emit progress();
  531. }
  532. }
  533. database->exec( "DROP TABLE recipes" );
  534. database->exec( "CREATE TABLE recipes (id INTEGER NOT NULL,title VARCHAR(200), yield_amount FLOAT, yield_amount_offset FLOAT, yield_type_id INTEGER DEFAULT '-1', instructions TEXT, photo BLOB, prep_time TIME, ctime TIMESTAMP, mtime TIMESTAMP, atime TIMESTAMP, PRIMARY KEY (id))" );
  535. copyQuery = database->exec( "SELECT id,title,yield_amount,yield_amount_offset,yield_type_id,instructions,photo,prep_time FROM recipes_copy" );
  536. if ( copyQuery.isActive() ) {
  537. TQString current_timestamp = TQDateTime::currentDateTime().toString(TQt::ISODate);
  538. while ( copyQuery.next() ) {
  539. command = "INSERT INTO recipes VALUES('"
  540. + escape( copyQuery.value( 0 ).toString() )
  541. + "','" + escape( copyQuery.value( 1 ).toString() )
  542. + "','" + escape( copyQuery.value( 2 ).toString() )
  543. + "','" + escape( copyQuery.value( 3 ).toString() )
  544. + "','" + escape( copyQuery.value( 4 ).toString() )
  545. + "','" + escape( copyQuery.value( 5 ).toString() )
  546. + "','" + escape( copyQuery.value( 6 ).toString() )
  547. + "','" + escape( copyQuery.value( 7 ).toString() )
  548. + "','" + escape( current_timestamp ) //ctime
  549. + "','" + escape( current_timestamp ) //mtime
  550. + "','" + escape( current_timestamp ) //atime
  551. + "')";
  552. database->exec( command );
  553. emit progress();
  554. }
  555. }
  556. database->exec( "DROP TABLE recipes_copy" );
  557. database->exec( "UPDATE db_info SET ver='0.84',generated_by='Krecipes SVN (20050913)';" );
  558. database->commit();
  559. }
  560. if ( tqRound(version*100) < 85 ) {
  561. database->transaction();
  562. TQSqlQuery query( "SELECT id,photo FROM recipes", database );
  563. if ( query.isActive() ) {
  564. while ( query.next() ) {
  565. TQImage photo;
  566. TQString photoString = query.value(1).toString();
  567. // Decode the photo
  568. uchar *photoArray = new uchar [ photoString.length() + 1 ];
  569. memcpy( photoArray, photoString.latin1(), photoString.length() * sizeof( char ) );
  570. sqlite_decode_binary( ( uchar* ) photoArray, ( uchar* ) photoArray );
  571. photo.loadFromData( photoArray, photoString.length() );
  572. // picture will now have a ready-to-use image
  573. delete[] photoArray;
  574. TQByteArray ba;
  575. TQBuffer buffer( ba );
  576. buffer.open( IO_WriteOnly );
  577. TQImageIO iio( &buffer, "JPEG" );
  578. iio.setImage( photo );
  579. iio.write();
  580. //recipe->photo.save( &buffer, "JPEG" ); don't need TQImageIO in QT 3.2
  581. storePhoto( query.value(0).toInt(), ba );
  582. emit progress();
  583. }
  584. }
  585. database->exec( "UPDATE db_info SET ver='0.85',generated_by='Krecipes SVN (20050926)';" );
  586. database->commit();
  587. }
  588. if ( tqRound(version*100) < 86 ) {
  589. database->transaction();
  590. database->exec( "CREATE index gidil_index ON ingredient_list(group_id)" );
  591. TQSqlQuery query( "SELECT id,name FROM ingredient_groups ORDER BY name", database );
  592. TQString last;
  593. int lastID;
  594. if ( query.isActive() ) {
  595. while ( query.next() ) {
  596. TQString name = query.value(1).toString();
  597. int id = query.value(0).toInt();
  598. if ( last == name ) {
  599. TQString command = TQString("UPDATE ingredient_list SET group_id=%1 WHERE group_id=%2").arg(lastID).arg(id);
  600. database->exec(command);
  601. command = TQString("DELETE FROM ingredient_groups WHERE id=%1").arg(id);
  602. database->exec(command);
  603. }
  604. last = name;
  605. lastID = id;
  606. emit progress();
  607. }
  608. }
  609. database->exec( "UPDATE db_info SET ver='0.86',generated_by='Krecipes SVN (20050928)'" );
  610. if ( !database->commit() )
  611. kdDebug()<<"Update to 0.86 failed. Maybe you should try again."<<endl;
  612. }
  613. if ( tqRound(version*100) < 87 ) {
  614. //Load this default data so the user knows what rating criteria is
  615. database->exec( TQString("INSERT INTO rating_criteria VALUES (1,'%1')").arg(i18n("Overall")) );
  616. database->exec( TQString("INSERT INTO rating_criteria VALUES (2,'%1')").arg(i18n("Taste") ) );
  617. database->exec( TQString("INSERT INTO rating_criteria VALUES (3,'%1')").arg(i18n("Appearance") ) );
  618. database->exec( TQString("INSERT INTO rating_criteria VALUES (4,'%1')").arg(i18n("Originality") ) );
  619. database->exec( TQString("INSERT INTO rating_criteria VALUES (5,'%1')").arg(i18n("Ease of Preparation") ) );
  620. database->exec( "UPDATE db_info SET ver='0.87',generated_by='Krecipes SVN (20051014)'" );
  621. }
  622. if ( tqRound(version*100) < 90 ) {
  623. database->exec("UPDATE db_info SET ver='0.9',generated_by='Krecipes 0.9'");
  624. }
  625. if ( tqRound(version*100) < 91 ) {
  626. database->exec("CREATE index parent_id_index ON categories(parent_id)");
  627. database->exec("UPDATE db_info SET ver='0.91',generated_by='Krecipes SVN (20060526)'");
  628. }
  629. if ( tqRound(version*100) < 92 ) {
  630. database->transaction();
  631. //==================add a columns to 'units' to allow unit abbreviations
  632. database->exec( "CREATE TABLE units_copy (id INTEGER NOT NULL, name VARCHAR(20), plural VARCHAR(20))" );
  633. TQSqlQuery copyQuery = database->exec( "SELECT id,name,plural FROM units" );
  634. if ( copyQuery.isActive() ) {
  635. while ( copyQuery.next() ) {
  636. command = "INSERT INTO units_copy VALUES('"
  637. + escape( copyQuery.value( 0 ).toString() ) //id
  638. + "','" + escape( copyQuery.value( 1 ).toString() ) //name
  639. + "','" + escape( copyQuery.value( 2 ).toString() ) //plural
  640. + "')";
  641. database->exec( command );
  642. emit progress();
  643. }
  644. }
  645. database->exec( "DROP TABLE units" );
  646. database->exec( "CREATE TABLE units (id INTEGER NOT NULL, name VARCHAR(20), name_abbrev VARCHAR(20), plural VARCHAR(20), plural_abbrev VARCHAR(20), PRIMARY KEY (id))" );
  647. copyQuery = database->exec( "SELECT id,name,plural FROM units_copy" );
  648. if ( copyQuery.isActive() ) {
  649. while ( copyQuery.next() ) {
  650. command = "INSERT INTO units VALUES('"
  651. + escape( copyQuery.value( 0 ).toString() ) //id
  652. + "','" + escape( copyQuery.value( 1 ).toString() ) //name
  653. + "',NULL" //name_abbrev
  654. + ",'" + escape( copyQuery.value( 2 ).toString() ) //plural
  655. + "',NULL" //plural_abbrev
  656. + ")";
  657. database->exec( command );
  658. emit progress();
  659. }
  660. }
  661. database->exec( "DROP TABLE units_copy" );
  662. database->exec("UPDATE db_info SET ver='0.92',generated_by='Krecipes SVN (20060609)'");
  663. if ( !database->commit() )
  664. kdDebug()<<"Update to 0.92 failed. Maybe you should try again."<<endl;
  665. }
  666. if ( tqRound(version*100) < 93 ) {
  667. database->transaction();
  668. addColumn("CREATE TABLE %1 (id INTEGER NOT NULL, recipe_id INTEGER, ingredient_id INTEGER, amount FLOAT, amount_offset FLOAT, unit_id INTEGER, order_index INTEGER, group_id INTEGER, %2 PRIMARY KEY(id) )","substitute_for INTEGER","NULL","ingredient_list",8);
  669. database->exec( "CREATE index ridil_index ON ingredient_list(recipe_id)" );
  670. database->exec( "CREATE index iidil_index ON ingredient_list(ingredient_id)" );
  671. database->exec( "CREATE index gidil_index ON ingredient_list(group_id)" );
  672. database->exec( "UPDATE db_info SET ver='0.93',generated_by='Krecipes SVN (20060616)';" );
  673. database->commit();
  674. }
  675. if ( tqRound(version*100) < 94 ) {
  676. database->transaction();
  677. //==================add a column to 'units' to allow specifying a type
  678. database->exec( "CREATE TABLE units_copy (id INTEGER NOT NULL, name VARCHAR(20), name_abbrev VARCHAR(20), plural VARCHAR(20), plural_abbrev VARCHAR(20))" );
  679. TQSqlQuery copyQuery = database->exec( "SELECT id,name,name_abbrev,plural,plural_abbrev FROM units" );
  680. if ( copyQuery.isActive() ) {
  681. while ( copyQuery.next() ) {
  682. TQString name_abbrev = escape( copyQuery.value( 2 ).toString() );
  683. if ( name_abbrev.isEmpty() )
  684. name_abbrev = "NULL";
  685. else {
  686. name_abbrev.prepend("'");
  687. name_abbrev.append("'");
  688. }
  689. TQString plural_abbrev = escape( copyQuery.value( 4 ).toString() );
  690. if ( plural_abbrev.isEmpty() )
  691. plural_abbrev = "NULL";
  692. else {
  693. plural_abbrev.prepend("'");
  694. plural_abbrev.append("'");
  695. }
  696. command = "INSERT INTO units_copy VALUES('"
  697. + escape( copyQuery.value( 0 ).toString() ) //id
  698. + "','" + escape( copyQuery.value( 1 ).toString() ) //name
  699. + "'," + name_abbrev //name_abbrev
  700. + ",'" + escape( copyQuery.value( 3 ).toString() ) //plural
  701. + "'," + plural_abbrev //plural_abbrev
  702. + ")";
  703. database->exec( command );
  704. emit progress();
  705. }
  706. }
  707. database->exec( "DROP TABLE units" );
  708. database->exec( "CREATE TABLE units (id INTEGER NOT NULL, name VARCHAR(20), name_abbrev VARCHAR(20), plural VARCHAR(20), plural_abbrev VARCHAR(20), type INTEGER NOT NULL, PRIMARY KEY (id))" );
  709. copyQuery = database->exec( "SELECT id,name,name_abbrev,plural,plural_abbrev FROM units_copy" );
  710. if ( copyQuery.isActive() ) {
  711. while ( copyQuery.next() ) {
  712. TQString name_abbrev = escape( copyQuery.value( 2 ).toString() );
  713. if ( name_abbrev.isEmpty() )
  714. name_abbrev = "NULL";
  715. else {
  716. name_abbrev.prepend("'");
  717. name_abbrev.append("'");
  718. }
  719. TQString plural_abbrev = escape( copyQuery.value( 4 ).toString() );
  720. if ( plural_abbrev.isEmpty() )
  721. plural_abbrev = "NULL";
  722. else {
  723. plural_abbrev.prepend("'");
  724. plural_abbrev.append("'");
  725. }
  726. command = "INSERT INTO units VALUES('"
  727. + escape( copyQuery.value( 0 ).toString() ) //id
  728. + "','" + escape( copyQuery.value( 1 ).toString() ) //name
  729. + "'," + name_abbrev //name_abbrev
  730. + ",'" + escape( copyQuery.value( 3 ).toString() ) //plural
  731. + "'," + plural_abbrev //plural_abbrev
  732. + ",'0')";
  733. database->exec( command );
  734. emit progress();
  735. }
  736. }
  737. database->exec( "DROP TABLE units_copy" );
  738. database->exec( "UPDATE db_info SET ver='0.94',generated_by='Krecipes SVN (20060712)';" );
  739. database->commit();
  740. }
  741. if ( tqRound(version*100) < 95 ) {
  742. database->exec( "DROP TABLE ingredient_weights" );
  743. createTable( "ingredient_weights" );
  744. database->exec( "UPDATE db_info SET ver='0.95',generated_by='Krecipes SVN (20060726)'" );
  745. }
  746. }
  747. void LiteRecipeDB::addColumn( const TQString &new_table_sql, const TQString &new_col_info, const TQString &default_value, const TQString &table_name, int col_index )
  748. {
  749. TQString command;
  750. command = TQString(new_table_sql).arg(table_name+"_copy").arg(TQString::null);
  751. kdDebug()<<"calling: "<<command<<endl;
  752. database->exec( command );
  753. command = "SELECT * FROM "+table_name;
  754. kdDebug()<<"calling: "<<command<<endl;
  755. TQSqlQuery copyQuery = database->exec( command );
  756. if ( copyQuery.isActive() ) {
  757. while ( copyQuery.next() ) {
  758. TQStringList dataList;
  759. for ( int i = 0 ;; ++i ) {
  760. if ( copyQuery.value(i).isNull() )
  761. break;
  762. TQString data = copyQuery.value(i).toString();
  763. dataList << "'"+escape(data)+"'";
  764. }
  765. command = "INSERT INTO "+table_name+"_copy VALUES("+dataList.join(",")+");";
  766. kdDebug()<<"calling: "<<command<<endl;
  767. database->exec( command );
  768. emit progress();
  769. }
  770. }
  771. database->exec( "DROP TABLE "+table_name );
  772. database->exec( TQString(new_table_sql).arg(table_name).arg(new_col_info+",") );
  773. copyQuery = database->exec( "SELECT * FROM "+table_name+"_copy" );
  774. if ( copyQuery.isActive() ) {
  775. while ( copyQuery.next() ) {
  776. TQStringList dataList;
  777. for ( int i = 0 ;; ++i ) {
  778. if ( i == col_index )
  779. dataList << default_value;
  780. if ( copyQuery.value(i).isNull() )
  781. break;
  782. TQString data = copyQuery.value(i).toString();
  783. dataList << "'"+escape(data)+"'";
  784. }
  785. command = "INSERT INTO "+table_name+" VALUES(" +dataList.join(",")+")";
  786. kdDebug()<<"calling: "<<command<<endl;
  787. database->exec( command );
  788. emit progress();
  789. }
  790. }
  791. database->exec( "DROP TABLE "+table_name+"_copy" );
  792. }
  793. TQString LiteRecipeDB::escapeAndEncode( const TQString &s ) const
  794. {
  795. TQString s_escaped;
  796. // Escape
  797. s_escaped = escape( TQString::fromLatin1(s.utf8()) );
  798. // Return encoded
  799. return s_escaped.latin1(); // Note that the text has already been converted before escaping.
  800. }
  801. /*
  802. ** Decode the string "in" into binary data and write it into "out".
  803. ** This routine reverses the encoding created by sqlite_encode_binary().
  804. ** The output will always be a few bytes less than the input. The number
  805. ** of bytes of output is returned. If the input is not a well-formed
  806. ** encoding, -1 is returned.
  807. **
  808. ** The "in" and "out" parameters may point to the same buffer in order
  809. ** to decode a string in place.
  810. */
  811. int sqlite_decode_binary( const unsigned char *in, unsigned char *out )
  812. {
  813. int i, c, e;
  814. e = *( in++ );
  815. i = 0;
  816. while ( ( c = *( in++ ) ) != 0 ) {
  817. if ( c == 1 ) {
  818. c = *( in++ );
  819. if ( c == 1 ) {
  820. c = 0;
  821. }
  822. else if ( c == 2 ) {
  823. c = 1;
  824. }
  825. else if ( c == 3 ) {
  826. c = '\'';
  827. }
  828. else {
  829. return -1;
  830. }
  831. }
  832. out[ i++ ] = ( c + e ) & 0xff;
  833. }
  834. return i;
  835. }
  836. TQString escape( const TQString &s )
  837. {
  838. TQString s_escaped = s;
  839. if ( !s_escaped.isEmpty() ) { //###: sqlite_mprintf() seems to fill an empty string with garbage
  840. // Escape using SQLite's function
  841. #if HAVE_SQLITE
  842. char * escaped = sqlite_mprintf( "%q", s.latin1() ); // Escape the string(allocates memory)
  843. #elif HAVE_SQLITE3
  844. char * escaped = sqlite3_mprintf( "%q", s.latin1() ); // Escape the string(allocates memory)
  845. #endif
  846. s_escaped = escaped;
  847. #if HAVE_SQLITE
  848. sqlite_freemem( escaped ); // free allocated memory
  849. #elif HAVE_SQLITE3
  850. sqlite3_free( escaped ); // free allocated memory
  851. #endif
  852. }
  853. return ( s_escaped );
  854. }
  855. #include "literecipedb.moc"