mirror of
				https://github.com/luanti-org/minetestmapper.git
				synced 2025-10-31 08:05:24 +01:00 
			
		
		
		
	Throwing exception from destructor is not recommended and generates lots of warnings during compilation. Don't use macro SQLRES, and: - ignore return code of sqlite3_finalize (of no interest here) - log to stderr sqlite3_close failure
		
			
				
	
	
		
			93 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <stdexcept>
 | |
| #include <unistd.h> // for usleep
 | |
| #include <iostream>
 | |
| #include "db-sqlite3.h"
 | |
| #include "types.h"
 | |
| 
 | |
| #define SQLRES(f, good) \
 | |
| 	result = (sqlite3_##f);\
 | |
| 	if (result != good) {\
 | |
| 		throw std::runtime_error(sqlite3_errmsg(db));\
 | |
| 	}
 | |
| #define SQLOK(f) SQLRES(f, SQLITE_OK)
 | |
| 
 | |
| 
 | |
| DBSQLite3::DBSQLite3(const std::string &mapdir)
 | |
| {
 | |
| 	int result;
 | |
| 	std::string db_name = mapdir + "map.sqlite";
 | |
| 
 | |
| 	SQLOK(open_v2(db_name.c_str(), &db, SQLITE_OPEN_READONLY |
 | |
| 			SQLITE_OPEN_PRIVATECACHE, 0))
 | |
| 
 | |
| 	SQLOK(prepare_v2(db,
 | |
| 			"SELECT pos, data FROM blocks WHERE pos BETWEEN ? AND ?",
 | |
| 		-1, &stmt_get_blocks_z, NULL))
 | |
| 
 | |
| 	SQLOK(prepare_v2(db,
 | |
| 			"SELECT pos FROM blocks",
 | |
| 		-1, &stmt_get_block_pos, NULL))
 | |
| }
 | |
| 
 | |
| 
 | |
| DBSQLite3::~DBSQLite3()
 | |
| {
 | |
| 	sqlite3_finalize(stmt_get_blocks_z);
 | |
| 	sqlite3_finalize(stmt_get_block_pos);
 | |
| 
 | |
| 	if (sqlite3_close(db) != SQLITE_OK) {
 | |
| 		std::cerr << "Error closing SQLite database." << std::endl;
 | |
| 	};
 | |
| }
 | |
| 
 | |
| std::vector<BlockPos> DBSQLite3::getBlockPos()
 | |
| {
 | |
| 	int result;
 | |
| 	std::vector<BlockPos> positions;
 | |
| 	while ((result = sqlite3_step(stmt_get_block_pos)) != SQLITE_DONE) {
 | |
| 		if (result == SQLITE_ROW) {
 | |
| 			int64_t posHash = sqlite3_column_int64(stmt_get_block_pos, 0);
 | |
| 			positions.push_back(decodeBlockPos(posHash));
 | |
| 		} else if (result == SQLITE_BUSY) { // Wait some time and try again
 | |
| 			usleep(10000);
 | |
| 		} else {
 | |
| 			throw std::runtime_error(sqlite3_errmsg(db));
 | |
| 		}
 | |
| 	}
 | |
| 	SQLOK(reset(stmt_get_block_pos));
 | |
| 	return positions;
 | |
| }
 | |
| 
 | |
| 
 | |
| void DBSQLite3::getBlocksOnZ(std::map<int16_t, BlockList> &blocks, int16_t zPos)
 | |
| {
 | |
| 	int result;
 | |
| 
 | |
| 	// Magic numbers!
 | |
| 	int64_t minPos = encodeBlockPos(BlockPos(0, -2048, zPos));
 | |
| 	int64_t maxPos = encodeBlockPos(BlockPos(0, 2048, zPos)) - 1;
 | |
| 
 | |
| 	SQLOK(bind_int64(stmt_get_blocks_z, 1, minPos));
 | |
| 	SQLOK(bind_int64(stmt_get_blocks_z, 2, maxPos));
 | |
| 
 | |
| 	while ((result = sqlite3_step(stmt_get_blocks_z)) != SQLITE_DONE) {
 | |
| 		if (result == SQLITE_ROW) {
 | |
| 			int64_t posHash = sqlite3_column_int64(stmt_get_blocks_z, 0);
 | |
| 			const unsigned char *data = reinterpret_cast<const unsigned char *>(
 | |
| 					sqlite3_column_blob(stmt_get_blocks_z, 1));
 | |
| 			size_t size = sqlite3_column_bytes(stmt_get_blocks_z, 1);
 | |
| 			Block b(decodeBlockPos(posHash), ustring(data, size));
 | |
| 			blocks[b.first.x].push_back(b);
 | |
| 		} else if (result == SQLITE_BUSY) { // Wait some time and try again
 | |
| 			usleep(10000);
 | |
| 		} else {
 | |
| 			throw std::runtime_error(sqlite3_errmsg(db));
 | |
| 		}
 | |
| 	}
 | |
| 	SQLOK(reset(stmt_get_blocks_z));
 | |
| }
 | |
| 
 | |
| #undef SQLRES
 | |
| #undef SQLOK
 | |
| 
 |