comparison Framework/Common/Query.cpp @ 0:7cea966b6829

initial commit
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 04 Jul 2018 08:16:29 +0200
parents
children 714c5d2bee76
comparison
equal deleted inserted replaced
-1:000000000000 0:7cea966b6829
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "Query.h"
23
24 #include <Core/Logging.h>
25 #include <Core/OrthancException.h>
26
27 #include <boost/regex.hpp>
28
29 namespace OrthancDatabases
30 {
31 class Query::Token : public boost::noncopyable
32 {
33 private:
34 bool isParameter_;
35 std::string content_;
36
37 public:
38 Token(bool isParameter,
39 const std::string& content) :
40 isParameter_(isParameter),
41 content_(content)
42 {
43 }
44
45 bool IsParameter() const
46 {
47 return isParameter_;
48 }
49
50 const std::string& GetContent() const
51 {
52 return content_;
53 }
54 };
55
56
57 void Query::Setup(const std::string& sql)
58 {
59 boost::regex regex("\\$\\{(.*?)\\}");
60
61 std::string::const_iterator last = sql.begin();
62 boost::sregex_token_iterator it(sql.begin(), sql.end(), regex, 0);
63 boost::sregex_token_iterator end;
64
65 while (it != end)
66 {
67 if (last != it->first)
68 {
69 tokens_.push_back(new Token(false, std::string(last, it->first)));
70 }
71
72 std::string parameter = *it;
73 assert(parameter.size() >= 3);
74 parameter = parameter.substr(2, parameter.size() - 3);
75
76 tokens_.push_back(new Token(true, parameter));
77 parameters_[parameter] = ValueType_Null;
78
79 last = it->second;
80
81 ++it;
82 }
83
84 if (last != sql.end())
85 {
86 tokens_.push_back(new Token(false, std::string(last, sql.end())));
87 }
88 }
89
90
91 Query::Query(const std::string& sql) :
92 readOnly_(false)
93 {
94 Setup(sql);
95 }
96
97
98 Query::Query(const std::string& sql,
99 bool readOnly) :
100 readOnly_(readOnly)
101 {
102 Setup(sql);
103 }
104
105
106 Query::~Query()
107 {
108 for (size_t i = 0; i < tokens_.size(); i++)
109 {
110 assert(tokens_[i] != NULL);
111 delete tokens_[i];
112 }
113 }
114
115
116 bool Query::HasParameter(const std::string& parameter) const
117 {
118 return parameters_.find(parameter) != parameters_.end();
119 }
120
121
122 ValueType Query::GetType(const std::string& parameter) const
123 {
124 Parameters::const_iterator found = parameters_.find(parameter);
125
126 if (found == parameters_.end())
127 {
128 LOG(ERROR) << "Inexistent parameter in a SQL query: " << parameter;
129 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem);
130 }
131 else
132 {
133 return found->second;
134 }
135 }
136
137
138 void Query::SetType(const std::string& parameter,
139 ValueType type)
140 {
141 Parameters::iterator found = parameters_.find(parameter);
142
143 if (found == parameters_.end())
144 {
145 LOG(ERROR) << "Ignoring inexistent parameter in a SQL query: " << parameter;
146 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
147 }
148 else
149 {
150 found->second = type;
151 }
152 }
153
154
155 void Query::Format(std::string& result,
156 IParameterFormatter& formatter) const
157 {
158 result.clear();
159
160 for (size_t i = 0; i < tokens_.size(); i++)
161 {
162 assert(tokens_[i] != NULL);
163
164 const std::string& content = tokens_[i]->GetContent();
165
166 if (tokens_[i]->IsParameter())
167 {
168 std::string parameter;
169 formatter.Format(parameter, content, GetType(content));
170 result += parameter;
171 }
172 else
173 {
174 result += content;
175 }
176 }
177 }
178 }