support signed integers, negative numbers; binary format change: encode numbers as SLEB128 v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Fri, 13 Dec 2019 22:19:41 +0100
branchv_0
changeset 23 d3bfbce022aa
parent 22 2135eeb1de78
child 24 884ece10575d
support signed integers, negative numbers; binary format change: encode numbers as SLEB128
src/SqlHandler.h
--- a/src/SqlHandler.h	Wed Oct 30 17:56:45 2019 +0100
+++ b/src/SqlHandler.h	Fri Dec 13 22:19:41 2019 +0100
@@ -103,7 +103,23 @@
 		else throw SqlException(L"Unable to get SQLite column name.");
 	}
 
-	// TODO: sqlite3_column_type
+	relpipe::writer::TypeId getColumType(int columnIndex) {
+		const char* type = sqlite3_column_decltype(stmt, columnIndex);
+
+		// TODO: sqlite3_column_decltype returns value only for columns of existing tables, not for dynamic expressions – SQLite uses dynamic types
+		// fprintf(stderr, "%d → %s\n", columnIndex, type);
+		// SELECT typeof(1+1); == "integer"
+		// https://www.sqlite.org/c3ref/column_decltype.html – sqlite3_column_decltype
+		// https://www.sqlite.org/c3ref/column_blob.html – sqlite3_column_type
+		// https://www.sqlite.org/datatype3.html – Datatypes In SQLite Version 3
+		// https://dba.stackexchange.com/questions/203220/sqlite-what-is-the-use-of-specifying-data-types
+
+		if (type == nullptr) return relpipe::writer::TypeId::STRING;
+		else if (strcmp(type, "integer") == 0) return relpipe::writer::TypeId::INTEGER;
+		else if (strcmp(type, "text") == 0) return relpipe::writer::TypeId::STRING;
+		else return relpipe::writer::TypeId::STRING;
+		// TODO: support also other data types
+	}
 
 	std::string getString(int columnIndex) {
 		const char* value = (const char*) sqlite3_column_text(stmt, columnIndex);
@@ -196,8 +212,7 @@
 		}
 
 		std::vector<relpipe::writer::AttributeMetadata> metadata;
-		// TODO: support also other data types
-		for (int i = 0; i < columnCount; i++) metadata.push_back({convertor.from_bytes(prepared->getColumName(i).c_str()), relpipe::writer::TypeId::STRING});
+		for (int i = 0; i < columnCount; i++) metadata.push_back({convertor.from_bytes(prepared->getColumName(i).c_str()), prepared->getColumType(i)});
 		relationalWriter->startRelation(statement.relation, metadata, true);
 
 		while (prepared->next()) {
@@ -348,7 +363,7 @@
 
 		// pass-through some relations:
 		for (const CopyRelations& copy : configuration.copyRelations) copyRelations(copy);
-		
+
 		connection->transactionCommit();
 
 		// delete or keep the file: