src/StreamRelationalWriter.h
author František Kučera <franta-hg@frantovo.cz>
Sat, 21 Jul 2018 23:01:47 +0200
branchv_0
changeset 12 640e88aedf8f
parent 11 27bc67e7c80f
child 13 e7234dd45166
permissions -rw-r--r--
code for table generation ported from the prototype: RelationalGenerator.h

#pragma once

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

#include "../include/typedefs.h"
#include "../include/RelationalWriter.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, string_t> > 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++) {
			wstring typeCode = attributes[c].second;
			integer_t typeId = toTypeId(typeCode);
			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);
		}
	}

};

}
}