src/StreamRelationalWriter.h
author František Kučera <franta-hg@frantovo.cz>
Sun, 22 Jul 2018 00:08:13 +0200
branchv_0
changeset 14 733334eca89b
parent 13 e7234dd45166
child 15 8fd6c4d44071
permissions -rw-r--r--
move create() method to a factory

#pragma once

#include <string>
#include <iostream>
#include <vector>

#include "../include/typedefs.h"
#include "../include/RelationalWriter.h"
#include "../include/TypeId.h"
#include "format.h"
#include "DataTypeWriterBase.h"
#include "types/BooleanDataTypeWriter.h"
#include "types/IntegerDataTypeWriter.h"
#include "types/StringDataTypeWriter.h"

namespace relpipe {
namespace writer {

class StreamRelationalWriter : public RelationalWriter {
private:
	std::ostream &output;
	types::BooleanDataTypeWriter booleanWriter;
	types::IntegerDataTypeWriter integerWriter;
	types::StringDataTypeWriter stringWriter;
	vector<DataTypeWriterBase*> writers = {&booleanWriter, &integerWriter, &stringWriter};
	
	/**
	 * count of columns in the current table
	 */
	integer_t columnCount;
	
	/**
	 * types of columns in the current table
	 */
	vector<integer_t> columnTypes;

	void writeString(const string_t &stringValue, const integer_t typeId) {
		for (DataTypeWriterBase* writer : writers) if (writer->supports(typeId)) return writer->writeString(output, stringValue);
		throw RelpipeWriterException(L"Unsupported data type: " + typeId);
	}

public:

	StreamRelationalWriter(std::ostream &output) :
	output(output) {
	}

	integer_t toTypeId(const string_t typeCode) override {
		for (DataTypeWriterBase* writer : writers) if (writer->supports(typeCode)) return writer->getTypeId();
		throw RelpipeWriterException(L"Unsupported data type: " + typeCode);
	}

	string_t toTypeCode(const integer_t typeId) override {
		for (DataTypeWriterBase* writer : writers) if (writer->supports(typeId)) return writer->getTypeCode();
		throw RelpipeWriterException(L"Unsupported data type: " + typeId);
	}

	void startRelation(string_t name, std::vector<std::pair<string_t, TypeId> > attributes, boolean_t writeHeader) override {
		string_t tableName = name;
		columnCount = attributes.size();

		// Write table name and column count:
		integerWriter.writeValue(output, DATA_PART_START);
		stringWriter.writeValue(output, tableName);
		integerWriter.writeValue(output, columnCount);

		columnTypes.clear();
		columnTypes.resize(columnCount);

		// Write column names:
		for (size_t c = 0; c < columnCount; c++) {
			wstring columnName = attributes[c].first;			
			stringWriter.writeValue(output, columnName);
		}

		// Write column types:
		for (size_t c = 0; c < columnCount; c++) {
			integer_t typeId = static_cast<integer_t>(attributes[c].second);
			integerWriter.writeValue(output, typeId);
			columnTypes[c] = typeId;
		}

	}

	void writeRecord(std::vector<string_t> attributes) override {
		// FIXME: check vector size
		for (size_t c = 0; c < columnCount; c++) {
			// TODO: support multiple rows in a single method call?
			if (c % columnCount == 0) {
				integerWriter.writeValue(output, DATA_PART_ROW);
			}

			wstring stringValue = attributes[c];
			integer_t typeId = columnTypes[c % columnCount];
			writeString(stringValue, typeId);
		}
	}

};

}
}