1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #pragma once
27 
28 #include "sqliteblob.h"
29 #include "sqliteglobal.h"
30 #include "sqlitevalue.h"
31 
32 #include <utils/smallstring.h>
33 
34 #include <memory>
35 #include <vector>
36 #include <iosfwd>
37 
38 struct sqlite3_changeset_iter;
39 
40 namespace Sqlite {
41 
42 class Sessions;
43 
44 enum class Operation : char { Invalid, Insert, Update, Delete };
45 
46 namespace SessionChangeSetInternal {
47 
48 class SentinelIterator
49 {};
50 
51 class ValueViews
52 {
53 public:
54     ValueView newValue;
55     ValueView oldValue;
56 };
57 
58 class SQLITE_EXPORT ConstTupleIterator
59 {
60 public:
61     using difference_type = int;
62     using value_type = ValueViews;
63     using pointer = const ValueViews *;
64     using reference = const ValueViews &;
65     using iterator_category = std::forward_iterator_tag;
66 
ConstTupleIterator(sqlite3_changeset_iter * sessionIterator,int index,Sqlite::Operation operation)67     ConstTupleIterator(sqlite3_changeset_iter *sessionIterator,
68                        int index,
69                        Sqlite::Operation operation)
70         : m_sessionIterator{sessionIterator}
71         , m_column{index}
72         , m_operation{operation}
73     {}
74 
75     ConstTupleIterator operator++()
76     {
77         ++m_column;
78 
79         return *this;
80     }
81 
82     friend bool operator==(const ConstTupleIterator &first, const ConstTupleIterator &second)
83     {
84         return first.m_column == second.m_column;
85     }
86 
87     friend bool operator!=(const ConstTupleIterator &first, const ConstTupleIterator &second)
88     {
89         return !(first == second);
90     }
91 
92     ValueViews operator*() const;
93 
94 private:
95     sqlite3_changeset_iter *m_sessionIterator = {};
96     int m_column = 0;
97     Sqlite::Operation m_operation = Sqlite::Operation::Invalid;
98 };
99 
100 class SQLITE_EXPORT Tuple
101 {
102 public:
103     using difference_type = int;
104     using value_type = ValueView;
105     using reference = ValueView &;
106     using const_reference = const ValueView &;
107     using iterator = ConstTupleIterator;
108     using const_iterator = ConstTupleIterator;
109     using size_type = int;
110 
111     Utils::SmallStringView table;
112     sqlite3_changeset_iter *sessionIterator = {};
113     int columnCount = 0;
114     Sqlite::Operation operation = Sqlite::Operation::Invalid;
115 
116     ValueViews operator[](int column) const;
begin()117     ConstTupleIterator begin() const { return {sessionIterator, 0, operation}; }
end()118     ConstTupleIterator end() const { return {sessionIterator, columnCount, operation}; }
119 };
120 
121 enum class State : char { Invalid, Row, Done };
122 
123 class SQLITE_EXPORT ConstIterator
124 {
125 public:
126     using difference_type = long;
127     using value_type = Tuple;
128     using pointer = const Tuple *;
129     using reference = const Tuple &;
130     using iterator_category = std::input_iterator_tag;
131 
ConstIterator(sqlite3_changeset_iter * sessionIterator)132     ConstIterator(sqlite3_changeset_iter *sessionIterator)
133         : m_sessionIterator(sessionIterator)
134     {}
135 
136     ConstIterator(const ConstIterator &) = delete;
137     void operator=(const ConstIterator &) = delete;
138 
ConstIterator(ConstIterator && other)139     ConstIterator(ConstIterator &&other)
140         : m_sessionIterator(other.m_sessionIterator)
141         , m_state(other.m_state)
142     {
143         other.m_sessionIterator = {};
144         other.m_state = State::Done;
145     }
146 
147     ConstIterator &operator=(ConstIterator &&other)
148     {
149         auto tmp = std::move(other);
150         swap(tmp, *this);
151 
152         return *this;
153     }
154 
155     ~ConstIterator();
156 
swap(ConstIterator & first,ConstIterator & second)157     friend void swap(ConstIterator &first, ConstIterator &second) noexcept
158     {
159         std::swap(first.m_sessionIterator, second.m_sessionIterator);
160         std::swap(first.m_state, second.m_state);
161     }
162 
163     ConstIterator &operator++();
164 
165     friend bool operator==(const ConstIterator &first, const ConstIterator &second)
166     {
167         return first.m_sessionIterator == second.m_sessionIterator;
168     }
169 
170     friend bool operator!=(const ConstIterator &first, const ConstIterator &second)
171     {
172         return !(first == second);
173     }
174 
175     friend bool operator==(const ConstIterator &first, SentinelIterator)
176     {
177         return first.m_state == State::Done;
178     }
179 
180     friend bool operator!=(const ConstIterator &first, SentinelIterator)
181     {
182         return first.m_state == State::Row;
183     }
184 
185     friend bool operator==(SentinelIterator first, const ConstIterator &second)
186     {
187         return second == first;
188     }
189 
190     friend bool operator!=(SentinelIterator first, const ConstIterator &second)
191     {
192         return second != first;
193     }
194 
195     Tuple operator*() const;
196 
state()197     State state() const { return m_state; }
198 
199 private:
200     sqlite3_changeset_iter *m_sessionIterator = {};
201     State m_state = State::Invalid;
202 };
203 } // namespace SessionChangeSetInternal
204 
205 class SQLITE_EXPORT SessionChangeSet
206 {
207 public:
208     SessionChangeSet(BlobView blob);
209     SessionChangeSet(Sessions &session);
210     ~SessionChangeSet();
211     SessionChangeSet(const SessionChangeSet &) = delete;
212     void operator=(const SessionChangeSet &) = delete;
SessionChangeSet(SessionChangeSet && other)213     SessionChangeSet(SessionChangeSet &&other) noexcept
214     {
215         SessionChangeSet temp;
216         swap(temp, other);
217         swap(temp, *this);
218     }
219     void operator=(SessionChangeSet &);
220 
221     BlobView asBlobView() const;
222 
swap(SessionChangeSet & first,SessionChangeSet & second)223     friend void swap(SessionChangeSet &first, SessionChangeSet &second) noexcept
224     {
225         SessionChangeSet temp;
226         std::swap(temp.m_data, first.m_data);
227         std::swap(temp.m_size, first.m_size);
228         std::swap(first.m_data, second.m_data);
229         std::swap(first.m_size, second.m_size);
230         std::swap(temp.m_data, second.m_data);
231         std::swap(temp.m_size, second.m_size);
232     }
233 
234     SessionChangeSetInternal::ConstIterator begin() const;
end()235     SessionChangeSetInternal::SentinelIterator end() const { return {}; }
236 
data()237     void *data() const { return m_data; }
238 
size()239     int size() const { return m_size; }
240 
241 private:
242     SessionChangeSet() = default;
243 
244 private:
245     void *m_data = nullptr;
246     int m_size = {};
247 };
248 
249 using SessionChangeSets = std::vector<SessionChangeSet>;
250 
251 } // namespace Sqlite
252