1 /** 2 * Orthanc - A Lightweight, RESTful DICOM Store 3 * 4 * Copyright (C) 2012-2016 Sebastien Jodogne <s.jodogne@orthanc-labs.com>, 5 * Medical Physics Department, CHU of Liege, Belgium 6 * 7 * Copyright (c) 2012 The Chromium Authors. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are 11 * met: 12 * 13 * * Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * * Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following disclaimer 17 * in the documentation and/or other materials provided with the 18 * distribution. 19 * * Neither the name of Google Inc., the name of the CHU of Liege, 20 * nor the names of its contributors may be used to endorse or promote 21 * products derived from this software without specific prior written 22 * permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 **/ 36 37 38 #if ORTHANC_SQLITE_STANDALONE != 1 39 #include "../PrecompiledHeaders.h" 40 #endif 41 42 #include "Statement.h" 43 #include "Connection.h" 44 45 #include <string.h> 46 #include <stdio.h> 47 #include <algorithm> 48 49 #if (ORTHANC_SQLITE_STANDALONE == 1) 50 // Trace logging is disabled if this SQLite wrapper is used 51 // independently of Orthanc 52 # define LOG_CREATE(message); 53 # define LOG_APPLY(message); 54 #elif defined(NDEBUG) 55 // Trace logging is disabled in release builds 56 # include "../Logging.h" 57 # define LOG_CREATE(message); 58 # define LOG_APPLY(message); 59 #else 60 // Trace logging is enabled in debug builds 61 # include "../Logging.h" 62 # define LOG_CREATE(message) CLOG(TRACE, SQLITE) << "SQLite::Statement create: " << message; 63 # define LOG_APPLY(message); // CLOG(TRACE, SQLITE) << "SQLite::Statement apply: " << message; 64 #endif 65 66 #include "sqlite3.h" 67 68 #if defined(_MSC_VER) 69 #define snprintf _snprintf 70 #endif 71 72 73 namespace Orthanc 74 { 75 namespace SQLite 76 { CheckError(int err,ErrorCode code) const77 int Statement::CheckError(int err, ErrorCode code) const 78 { 79 bool succeeded = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE); 80 if (!succeeded) 81 { 82 #if ORTHANC_SQLITE_STANDALONE != 1 83 char buffer[128]; 84 snprintf(buffer, sizeof(buffer) - 1, "SQLite error code %d", err); 85 LOG(ERROR) << buffer; 86 #endif 87 88 throw OrthancSQLiteException(code); 89 } 90 91 return err; 92 } 93 CheckOk(int err,ErrorCode code) const94 void Statement::CheckOk(int err, ErrorCode code) const 95 { 96 if (err == SQLITE_RANGE) 97 { 98 // Binding to a non-existent variable is evidence of a serious error. 99 throw OrthancSQLiteException(ErrorCode_SQLiteBindOutOfRange); 100 } 101 else if (err != SQLITE_OK) 102 { 103 #if ORTHANC_SQLITE_STANDALONE != 1 104 char buffer[128]; 105 snprintf(buffer, sizeof(buffer) - 1, "SQLite error code %d", err); 106 LOG(ERROR) << buffer; 107 #endif 108 109 throw OrthancSQLiteException(code); 110 } 111 } 112 113 Statement(Connection & database,const StatementId & id,const std::string & sql)114 Statement::Statement(Connection& database, 115 const StatementId& id, 116 const std::string& sql) : 117 reference_(database.GetCachedStatement(id, sql.c_str())) 118 { 119 Reset(true); 120 LOG_CREATE(sql); 121 } 122 123 Statement(Connection & database,const StatementId & id,const char * sql)124 Statement::Statement(Connection& database, 125 const StatementId& id, 126 const char* sql) : 127 reference_(database.GetCachedStatement(id, sql)) 128 { 129 Reset(true); 130 LOG_CREATE(sql); 131 } 132 ~Statement()133 Statement::~Statement() 134 { 135 Reset(); 136 } 137 138 Statement(Connection & database,const std::string & sql)139 Statement::Statement(Connection& database, 140 const std::string& sql) : 141 reference_(database.GetWrappedObject(), sql.c_str()) 142 { 143 LOG_CREATE(sql); 144 } 145 146 Statement(Connection & database,const char * sql)147 Statement::Statement(Connection& database, 148 const char* sql) : 149 reference_(database.GetWrappedObject(), sql) 150 { 151 LOG_CREATE(sql); 152 } 153 154 Run()155 bool Statement::Run() 156 { 157 LOG_APPLY(sqlite3_sql(GetStatement())); 158 159 return CheckError(sqlite3_step(GetStatement()), ErrorCode_SQLiteCannotRun) == SQLITE_DONE; 160 } 161 Step()162 bool Statement::Step() 163 { 164 LOG_APPLY(sqlite3_sql(GetStatement())); 165 166 return CheckError(sqlite3_step(GetStatement()), ErrorCode_SQLiteCannotStep) == SQLITE_ROW; 167 } 168 Reset(bool clear_bound_vars)169 void Statement::Reset(bool clear_bound_vars) 170 { 171 // We don't call CheckError() here because sqlite3_reset() returns 172 // the last error that Step() caused thereby generating a second 173 // spurious error callback. 174 if (clear_bound_vars) 175 sqlite3_clear_bindings(GetStatement()); 176 //CLOG(TRACE, SQLITE) << "SQLite::Statement::Reset"; 177 sqlite3_reset(GetStatement()); 178 } 179 GetOriginalSQLStatement()180 std::string Statement::GetOriginalSQLStatement() 181 { 182 return std::string(sqlite3_sql(GetStatement())); 183 } 184 185 BindNull(int col)186 void Statement::BindNull(int col) 187 { 188 CheckOk(sqlite3_bind_null(GetStatement(), col + 1), 189 ErrorCode_BadParameterType); 190 } 191 BindBool(int col,bool val)192 void Statement::BindBool(int col, bool val) 193 { 194 BindInt(col, val ? 1 : 0); 195 } 196 BindInt(int col,int val)197 void Statement::BindInt(int col, int val) 198 { 199 CheckOk(sqlite3_bind_int(GetStatement(), col + 1, val), 200 ErrorCode_BadParameterType); 201 } 202 BindInt64(int col,int64_t val)203 void Statement::BindInt64(int col, int64_t val) 204 { 205 CheckOk(sqlite3_bind_int64(GetStatement(), col + 1, val), 206 ErrorCode_BadParameterType); 207 } 208 BindDouble(int col,double val)209 void Statement::BindDouble(int col, double val) 210 { 211 CheckOk(sqlite3_bind_double(GetStatement(), col + 1, val), 212 ErrorCode_BadParameterType); 213 } 214 BindCString(int col,const char * val)215 void Statement::BindCString(int col, const char* val) 216 { 217 CheckOk(sqlite3_bind_text(GetStatement(), col + 1, val, -1, SQLITE_TRANSIENT), 218 ErrorCode_BadParameterType); 219 } 220 BindString(int col,const std::string & val)221 void Statement::BindString(int col, const std::string& val) 222 { 223 CheckOk(sqlite3_bind_text(GetStatement(), 224 col + 1, 225 val.data(), 226 static_cast<int>(val.size()), 227 SQLITE_TRANSIENT), 228 ErrorCode_BadParameterType); 229 } 230 231 /*void Statement::BindString16(int col, const string16& value) 232 { 233 BindString(col, UTF16ToUTF8(value)); 234 }*/ 235 BindBlob(int col,const void * val,int val_len)236 void Statement::BindBlob(int col, const void* val, int val_len) 237 { 238 CheckOk(sqlite3_bind_blob(GetStatement(), col + 1, val, val_len, SQLITE_TRANSIENT), 239 ErrorCode_BadParameterType); 240 } 241 242 ColumnCount() const243 int Statement::ColumnCount() const 244 { 245 return sqlite3_column_count(GetStatement()); 246 } 247 248 GetColumnType(int col) const249 ColumnType Statement::GetColumnType(int col) const 250 { 251 // Verify that our enum matches sqlite's values. 252 assert(COLUMN_TYPE_INTEGER == SQLITE_INTEGER); 253 assert(COLUMN_TYPE_FLOAT == SQLITE_FLOAT); 254 assert(COLUMN_TYPE_TEXT == SQLITE_TEXT); 255 assert(COLUMN_TYPE_BLOB == SQLITE_BLOB); 256 assert(COLUMN_TYPE_NULL == SQLITE_NULL); 257 258 return static_cast<ColumnType>(sqlite3_column_type(GetStatement(), col)); 259 } 260 GetDeclaredColumnType(int col) const261 ColumnType Statement::GetDeclaredColumnType(int col) const 262 { 263 std::string column_type(sqlite3_column_decltype(GetStatement(), col)); 264 std::transform(column_type.begin(), column_type.end(), column_type.begin(), tolower); 265 266 if (column_type == "integer") 267 return COLUMN_TYPE_INTEGER; 268 else if (column_type == "float") 269 return COLUMN_TYPE_FLOAT; 270 else if (column_type == "text") 271 return COLUMN_TYPE_TEXT; 272 else if (column_type == "blob") 273 return COLUMN_TYPE_BLOB; 274 275 return COLUMN_TYPE_NULL; 276 } 277 ColumnIsNull(int col) const278 bool Statement::ColumnIsNull(int col) const 279 { 280 return sqlite3_column_type(GetStatement(), col) == SQLITE_NULL; 281 } 282 ColumnBool(int col) const283 bool Statement::ColumnBool(int col) const 284 { 285 return !!ColumnInt(col); 286 } 287 ColumnInt(int col) const288 int Statement::ColumnInt(int col) const 289 { 290 return sqlite3_column_int(GetStatement(), col); 291 } 292 ColumnInt64(int col) const293 int64_t Statement::ColumnInt64(int col) const 294 { 295 return sqlite3_column_int64(GetStatement(), col); 296 } 297 ColumnDouble(int col) const298 double Statement::ColumnDouble(int col) const 299 { 300 return sqlite3_column_double(GetStatement(), col); 301 } 302 ColumnString(int col) const303 std::string Statement::ColumnString(int col) const 304 { 305 const char* str = reinterpret_cast<const char*>( 306 sqlite3_column_text(GetStatement(), col)); 307 int len = sqlite3_column_bytes(GetStatement(), col); 308 309 std::string result; 310 if (str && len > 0) 311 result.assign(str, len); 312 return result; 313 } 314 315 /*string16 Statement::ColumnString16(int col) const 316 { 317 std::string s = ColumnString(col); 318 return !s.empty() ? UTF8ToUTF16(s) : string16(); 319 }*/ 320 ColumnByteLength(int col) const321 int Statement::ColumnByteLength(int col) const 322 { 323 return sqlite3_column_bytes(GetStatement(), col); 324 } 325 ColumnBlob(int col) const326 const void* Statement::ColumnBlob(int col) const 327 { 328 return sqlite3_column_blob(GetStatement(), col); 329 } 330 ColumnBlobAsString(int col,std::string * blob)331 bool Statement::ColumnBlobAsString(int col, std::string* blob) 332 { 333 const void* p = ColumnBlob(col); 334 size_t len = ColumnByteLength(col); 335 blob->resize(len); 336 if (blob->size() != len) { 337 return false; 338 } 339 blob->assign(reinterpret_cast<const char*>(p), len); 340 return true; 341 } 342 343 /*bool Statement::ColumnBlobAsString16(int col, string16* val) const 344 { 345 const void* data = ColumnBlob(col); 346 size_t len = ColumnByteLength(col) / sizeof(char16); 347 val->resize(len); 348 if (val->size() != len) 349 return false; 350 val->assign(reinterpret_cast<const char16*>(data), len); 351 return true; 352 }*/ 353 354 /*bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const 355 { 356 val->clear(); 357 358 const void* data = sqlite3_column_blob(GetStatement(), col); 359 int len = sqlite3_column_bytes(GetStatement(), col); 360 if (data && len > 0) { 361 val->resize(len); 362 memcpy(&(*val)[0], data, len); 363 } 364 return true; 365 }*/ 366 367 /*bool Statement::ColumnBlobAsVector( 368 int col, 369 std::vector<unsigned char>* val) const 370 { 371 return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val)); 372 }*/ 373 374 } 375 } 376