File: SequentialConnection.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (153 lines) | stat: -rw-r--r-- 4,838 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#pragma once
#include "SQL.h"

namespace sql {

	class SequentialStatement;

	/**
	 * Wrapper over the connection interface for database connections that communicate with the
	 * database over a sequential connection (e.g. a socket). This type of connections typically
	 * typically disallow performing any other operations while the results from a prepared
	 * statement are fetched. As such, the implementation adapts the standard interface to a
	 * "sequential interface" and introduces buffering and delays as necessary.
	 *
	 * The class does two things to make operations sequential:
	 * - Store the results from a query in RAM if the user of the interface attempts to do
	 *   anything before results are fetched to completion.
	 * - Delay finalization of prepared statements if results are being fetched.
	 */
	class SequentialConnection : public DBConnection {
		STORM_ABSTRACT_CLASS;
	public:
		// Create.
		STORM_CTOR SequentialConnection();

	protected:
		// May be called at any time to ensure that no fetches are underway. This causes us to store
		// the remaining rows in RAM until they are either consumed or discarded.
		void clearFetch();

		// Same as 'clearFetch', but does nothing if we are the statement currently fetching data.
		void clearFetch(SequentialStatement *stmt);

		// Is the specified statement free to fetch at the moment?
		Bool isFetching(SequentialStatement *stmt);

		/**
		 * Additional interface that should be implemented by derived classes.
		 */

		// Called to finalize a prepared statement. This logic needs to be implemented here since
		// vtables don't work after the destructor of SequentialStatement have been executed.
		virtual void STORM_FN finalizeStmt(SequentialStatement *stmt) ABSTRACT;

	private:
		// Interface intended to be used from SequentialStatement.
		friend class SequentialStatement;

		// Called by Stmt when we start fetching data.
		void startFetch(SequentialStatement *stmt);

		// Called by Stmt when it is done fetching data.
		void doneFetch(SequentialStatement *stmt);

		// Called by Stmt when it wishes to be finalize.
		void onFinalize(SequentialStatement *stmt);

	private:
		// Queue of statements that should be finalized when the opportunity arises, forming a
		// linked list.
		SequentialStatement *toFinalize;

		// Statement that is currently fetching data, if any.
		SequentialStatement *currentFetching;

		// Keep track of active statements

		// Run finalizers.
		void finalizeAll();
	};


	/**
	 * Custom statement for sequential connections.
	 *
	 * Most operations call back into SequentialConnection. Each database connection will however
	 * need to handle binding parameters since that is expected to be possible without communicating
	 * to the database itself.
	 */
	class SequentialStatement : public Statement {
		STORM_ABSTRACT_CLASS;
	public:
		// Create.
		STORM_CTOR SequentialStatement(SequentialConnection *connection);

		// Destroy, automatically call finalize if necessary.
		virtual ~SequentialStatement();

		// Execute the statement. Derived classes should override 'executeSeq' instead.
		Statement::Result STORM_FN execute() override;

		// Finalize the statement. Derived classes should override 'finalizeStmt' in the base class instead.
		void STORM_FN finalize() override;

	protected:
		/**
		 * New functionality for derived classes.
		 */

		// Get owning connection.
		SequentialConnection *connection() const { return owner; }

		// Derived classes should call this function when an execute call is known to not produce
		// any data. Otherwise returning null from 'nextRowSeq' is enough.
		void STORM_FN fetchDone();


		/**
		 * Interception of existing interface.
		 */

		// Called when the result should be disposed.
		void STORM_FN disposeResult() override;

		// Called to get the next result. Override 'nextRowSeq' instead.
		Maybe<Row> STORM_FN nextRow() override;


		/**
		 * New interface.
		 */

		// Called when the statement should be executed. Returns 'true' if there may be something to
		// get through 'nextRowSeq'.
		virtual Bool STORM_FN executeSeq() ABSTRACT;

		// Called when any remaining results should be disposed.
		virtual void STORM_FN disposeResultSeq() ABSTRACT;

		// Called to get the next row.
		virtual Maybe<Row> STORM_FN nextRowSeq() ABSTRACT;

	private:
		friend class SequentialConnection;

		// Linked list of statements that the connection should finalize. Note that the objects in
		// here might be destroyed, and virtual functions may not work as expected.
		SequentialStatement *toFinalize;

		// Associated connection.
		SequentialConnection *owner;

		// Buffered rows if necessary.
		Array<Row> *buffer;

		// Reached the end of the actual DB connection's stream?
		Bool atEnd;

		// Buffer all elements. Called by SequentialConnection.
		void fetchAll();
	};

}