comparison MySQL/Plugins/MySQLStorageArea.cpp @ 242:b97a537f4613

MySQL: Support of range reads for the storage area
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 13 Apr 2021 17:00:02 +0200
parents 35598014f140
children 29ac6f4a0f45
comparison
equal deleted inserted replaced
241:a063bbf10a3e 242:b97a537f4613
19 **/ 19 **/
20 20
21 21
22 #include "MySQLStorageArea.h" 22 #include "MySQLStorageArea.h"
23 23
24 #include "../../Framework/Common/BinaryStringValue.h"
24 #include "../../Framework/MySQL/MySQLDatabase.h" 25 #include "../../Framework/MySQL/MySQLDatabase.h"
25 #include "../../Framework/MySQL/MySQLTransaction.h" 26 #include "../../Framework/MySQL/MySQLTransaction.h"
26 #include "MySQLDefinitions.h" 27 #include "MySQLDefinitions.h"
27 28
28 #include <Compatibility.h> // For std::unique_ptr<> 29 #include <Compatibility.h> // For std::unique_ptr<>
96 } 97 }
97 98
98 ConfigureDatabase(*database, parameters, clearAll); 99 ConfigureDatabase(*database, parameters, clearAll);
99 SetDatabase(database.release()); 100 SetDatabase(database.release());
100 } 101 }
102
103
104 class MySQLStorageArea::Accessor : public StorageBackend::AccessorBase
105 {
106 public:
107 Accessor(MySQLStorageArea& backend) :
108 AccessorBase(backend)
109 {
110 }
111
112 virtual void ReadRange(IFileContentVisitor& visitor,
113 const std::string& uuid,
114 OrthancPluginContentType type,
115 uint64_t start,
116 uint64_t length) ORTHANC_OVERRIDE
117 {
118 DatabaseManager::Transaction transaction(GetManager(), TransactionType_ReadOnly);
119
120 {
121 // https://stackoverflow.com/a/6545557/881731
122 DatabaseManager::CachedStatement statement(
123 STATEMENT_FROM_HERE, GetManager(),
124 "SELECT SUBSTRING(content, ${start}, ${length}) FROM StorageArea WHERE uuid=${uuid} AND type=${type}");
125
126 statement.SetParameterType("uuid", ValueType_Utf8String);
127 statement.SetParameterType("type", ValueType_Integer64);
128 statement.SetParameterType("start", ValueType_Integer64);
129 statement.SetParameterType("length", ValueType_Integer64);
130
131 Dictionary args;
132 args.SetUtf8Value("uuid", uuid);
133 args.SetIntegerValue("type", type);
134 args.SetIntegerValue("length", length);
135
136 /**
137 * "For all forms of SUBSTRING(), the position of the first
138 * character in the string from which the substring is to be
139 * extracted is reckoned as 1." => hence the "+ 1"
140 * https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substring
141 **/
142 args.SetIntegerValue("start", start + 1);
143
144 statement.Execute(args);
145
146 if (statement.IsDone())
147 {
148 throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
149 }
150 else if (statement.GetResultFieldsCount() != 1)
151 {
152 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database);
153 }
154 else
155 {
156 const IValue& value = statement.GetResultField(0);
157
158 if (value.GetType() == ValueType_BinaryString)
159 {
160 const std::string& content = dynamic_cast<const BinaryStringValue&>(value).GetContent();
161
162 if (static_cast<uint64_t>(content.size()) == length)
163 {
164 visitor.Assign(content);
165 }
166 else
167 {
168 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRange);
169 }
170 }
171 else
172 {
173 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database);
174 }
175 }
176 }
177
178 transaction.Commit();
179
180 if (!visitor.IsSuccess())
181 {
182 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database, "Could not read range from the storage area");
183 }
184 }
185 };
186
187
188 StorageBackend::IAccessor* MySQLStorageArea::CreateAccessor()
189 {
190 return new Accessor(*this);
191 }
101 } 192 }