/* Minetest-c55 Copyright (C) 2010-2011 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Author: Jan Cychnerski */ #include "db.h" using namespace std; /* bool */ template<> const std::string DBTypeTraits::name = "INT"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, bool& val) { val = sqlite3_column_int(stmt,iCol) != 0; } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const bool& val) { bool d = sqlite3_bind_int(stmt,num,val?1:0); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* int */ template<> const std::string DBTypeTraits::name = "INT"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, int& val) { val = sqlite3_column_int(stmt,iCol); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const int& val) { int d = sqlite3_bind_int(stmt,num,val); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* unsigned int */ template<> const std::string DBTypeTraits::name = "INT"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, unsigned int& val) { val = sqlite3_column_int(stmt,iCol); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const unsigned int& val) { int d = sqlite3_bind_int(stmt,num,val); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* u64, db_key */ template<> const std::string DBTypeTraits::name = "INT"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, u64& val) { val = sqlite3_column_int64(stmt,iCol); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const u64& val) { u64 d = sqlite3_bind_int64(stmt,num,val); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } template<> const std::string DBTypeTraits::name = "INT"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, db_key& val) { val = sqlite3_column_int64(stmt,iCol); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const db_key& val) { db_key d = sqlite3_bind_int64(stmt,num,val); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* v3s16 */ template<> const std::string DBTypeTraits::name = "INT"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, v3s16& val) { val = DBKey( sqlite3_column_int64(stmt,iCol) ); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const v3s16& val) { int d = sqlite3_bind_int64(stmt,num,DBKey(val)); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* v2s16 */ template<> const std::string DBTypeTraits::name = "INT"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, v2s16 & val) { val = DBKey( sqlite3_column_int64(stmt,iCol) ); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const v2s16& val) { int d = sqlite3_bind_int64(stmt,num,DBKey(val)); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* v3f */ template<> const std::string DBTypeTraits::name = "BLOB"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, v3f& val) { if(sqlite3_column_bytes(stmt,iCol) != 12) throw DatabaseException("Value is not v3f"); const f32* data = (const f32*)sqlite3_column_blob(stmt,iCol); val.X = data[0]; val.Y = data[1]; val.Z = data[2]; } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const v3f& val) { const float data[3] = {val.X, val.Y, val.Z}; int d = sqlite3_bind_blob(stmt,num,data,12,SQLITE_TRANSIENT); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* string - stored as BLOB (!) */ template<> const std::string DBTypeTraits::name = "BLOB"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, std::string& val) { const char * data = (const char *)sqlite3_column_blob(stmt,iCol); size_t len = sqlite3_column_bytes(stmt,iCol); val.assign(data,len); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const std::string& val) { int d = sqlite3_bind_blob(stmt,num,val.c_str(),val.length(),NULL); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* float */ template<> const std::string DBTypeTraits::name = "REAL"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, float& val) { val = (float)sqlite3_column_double(stmt,iCol); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const float& val) { float d = sqlite3_bind_double(stmt,num,val); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* double */ template<> const std::string DBTypeTraits::name = "REAL"; template<> void DBTypeTraits::getColumn(sqlite3_stmt *stmt, int iCol, double& val) { val = sqlite3_column_double(stmt,iCol); } template<> void DBTypeTraits::bind(sqlite3_stmt* stmt, int num, const double& val) { double d = sqlite3_bind_double(stmt,num,val); if(d != SQLITE_OK) throw DatabaseException("Bind error"); } /* ITable */ ITable::ITable(sqlite3* database, const std::string& name, const std::string& key, const std::string& data, bool old_names): name(name), key_name(key), data_name(data), old_names(old_names), m_database(database) { assert(database); create(); int d; std::string q; std::string id_name = old_names ? "pos" : "id"; q = "SELECT `data` FROM `"+name+"` WHERE `"+id_name+"`=? LIMIT 1"; d = sqlite3_prepare_v2(m_database,q.c_str(), -1, &m_read, NULL); if(d != SQLITE_OK) { //infostream<<"WARNING: Database read statment failed to prepare: "<& ptr = tables[name]; if(ptr==NULL) ptr = new ITable(m_database,name,"BLOB","BLOB",old_names); return *ptr; }