1 // Copyright (c) 1999-2018 David Muse
2 // See the file COPYING for more information
3
4 #include <sqlrelay/sqlrserver.h>
5
6 #include <rudiments/process.h>
7 #include <rudiments/character.h>
8 #include <rudiments/stdio.h>
9 //#define DEBUG_MESSAGES 1
10 #include <rudiments/debugprint.h>
11
12 #include <config.h>
13
14 #ifndef SQLRELAY_ENABLE_SHARED
15 extern "C" {
16 #include "sqlrbindvariabletranslationdeclarations.cpp"
17 }
18 #endif
19
20 class sqlrbindvariabletranslationplugin {
21 public:
22 sqlrbindvariabletranslation *bvtr;
23 dynamiclib *dl;
24 const char *module;
25 };
26
27 class sqlrbindvariabletranslationsprivate {
28 friend class sqlrbindvariabletranslations;
29 private:
30 sqlrservercontroller *_cont;
31
32 bool _debug;
33
34 singlylinkedlist< sqlrbindvariabletranslationplugin * > _tlist;
35
36 const char *_error;
37 };
38
sqlrbindvariabletranslations(sqlrservercontroller * cont)39 sqlrbindvariabletranslations::sqlrbindvariabletranslations(
40 sqlrservercontroller *cont) {
41
42 debugFunction();
43 pvt=new sqlrbindvariabletranslationsprivate;
44 pvt->_cont=cont;
45 pvt->_debug=cont->getConfig()->getDebugBindVariableTranslations();
46 pvt->_error=NULL;
47 }
48
~sqlrbindvariabletranslations()49 sqlrbindvariabletranslations::~sqlrbindvariabletranslations() {
50 debugFunction();
51 unload();
52 delete pvt;
53 }
54
load(domnode * parameters)55 bool sqlrbindvariabletranslations::load(domnode *parameters) {
56 debugFunction();
57
58 unload();
59
60 // run through the bind variable translation list
61 for (domnode *bindvariabletranslation=parameters->getFirstTagChild();
62 !bindvariabletranslation->isNullNode();
63 bindvariabletranslation=
64 bindvariabletranslation->getNextTagSibling()) {
65
66 // load bind variable translation
67 loadBindVariableTranslation(bindvariabletranslation);
68 }
69
70 return true;
71 }
72
unload()73 void sqlrbindvariabletranslations::unload() {
74 debugFunction();
75 for (singlylinkedlistnode< sqlrbindvariabletranslationplugin * > *node=
76 pvt->_tlist.getFirst();
77 node; node=node->getNext()) {
78 sqlrbindvariabletranslationplugin *sqlt=node->getValue();
79 delete sqlt->bvtr;
80 delete sqlt->dl;
81 delete sqlt;
82 }
83 pvt->_tlist.clear();
84 }
85
loadBindVariableTranslation(domnode * bindvariabletranslation)86 void sqlrbindvariabletranslations::loadBindVariableTranslation(
87 domnode *bindvariabletranslation) {
88 debugFunction();
89
90 // ignore non-bindvariabletranslations
91 if (charstring::compare(bindvariabletranslation->getName(),
92 "bindvariabletranslation")) {
93 return;
94 }
95
96 // get the bind variable translation name
97 const char *module=
98 bindvariabletranslation->getAttributeValue("module");
99 if (!charstring::length(module)) {
100 // try "file", that's what it used to be called
101 module=bindvariabletranslation->getAttributeValue("file");
102 if (!charstring::length(module)) {
103 return;
104 }
105 }
106
107 if (pvt->_debug) {
108 stdoutput.printf("loading bind variable translation: %s\n",
109 module);
110 }
111
112 #ifdef SQLRELAY_ENABLE_SHARED
113 // load the bind variable translation module
114 stringbuffer modulename;
115 modulename.append(pvt->_cont->getPaths()->getLibExecDir());
116 modulename.append(SQLR);
117 modulename.append("bindvariabletranslation_");
118 modulename.append(module)->append(".")->append(SQLRELAY_MODULESUFFIX);
119 dynamiclib *dl=new dynamiclib();
120 if (!dl->open(modulename.getString(),true,true)) {
121 stdoutput.printf("failed to load bind variable "
122 "translation module: %s\n",module);
123 char *error=dl->getError();
124 stdoutput.printf("%s\n",(error)?error:"");
125 delete[] error;
126 delete dl;
127 return;
128 }
129
130 // load the bind variable translation itself
131 stringbuffer functionname;
132 functionname.append("new_sqlrbindvariabletranslation_")->append(module);
133 sqlrbindvariabletranslation *(*newBindVariableTranslation)
134 (sqlrservercontroller *,
135 sqlrbindvariabletranslations *,
136 domnode *)=
137 (sqlrbindvariabletranslation *(*)
138 (sqlrservercontroller *,
139 sqlrbindvariabletranslations *,
140 domnode *))
141 dl->getSymbol(functionname.getString());
142 if (!newBindVariableTranslation) {
143 stdoutput.printf("failed to load "
144 "bind variable translation: %s\n",module);
145 char *error=dl->getError();
146 stdoutput.printf("%s\n",(error)?error:"");
147 delete[] error;
148 dl->close();
149 delete dl;
150 return;
151 }
152 sqlrbindvariabletranslation *bvtr=
153 (*newBindVariableTranslation)
154 (pvt->_cont,this,bindvariabletranslation);
155
156 #else
157 dynamiclib *dl=NULL;
158 sqlrbindvariabletranslation *bvtr;
159 #include "sqlrbindvariabletranslationassignments.cpp"
160 {
161 bvtr=NULL;
162 }
163 #endif
164
165 if (pvt->_debug) {
166 stdoutput.printf("success\n");
167 }
168
169 // add the plugin to the list
170 sqlrbindvariabletranslationplugin *sqlrrstp=
171 new sqlrbindvariabletranslationplugin;
172 sqlrrstp->bvtr=bvtr;
173 sqlrrstp->dl=dl;
174 sqlrrstp->module=module;
175 pvt->_tlist.append(sqlrrstp);
176 }
177
run(sqlrserverconnection * sqlrcon,sqlrservercursor * sqlrcur)178 bool sqlrbindvariabletranslations::run(sqlrserverconnection *sqlrcon,
179 sqlrservercursor *sqlrcur) {
180 debugFunction();
181
182 pvt->_error=NULL;
183
184 for (singlylinkedlistnode< sqlrbindvariabletranslationplugin * > *node=
185 pvt->_tlist.getFirst();
186 node; node=node->getNext()) {
187 if (pvt->_debug) {
188 stdoutput.printf("\nrunning translation: %s...\n\n",
189 node->getValue()->module);
190 }
191
192 if (!node->getValue()->bvtr->run(sqlrcon,sqlrcur)) {
193 pvt->_error=node->getValue()->bvtr->getError();
194 return false;
195 }
196 }
197 return true;
198 }
199
getError()200 const char *sqlrbindvariabletranslations::getError() {
201 return pvt->_error;
202 }
203
endTransaction(bool commit)204 void sqlrbindvariabletranslations::endTransaction(bool commit) {
205 for (singlylinkedlistnode< sqlrbindvariabletranslationplugin * > *node=
206 pvt->_tlist.getFirst();
207 node; node=node->getNext()) {
208 node->getValue()->bvtr->endTransaction(commit);
209 }
210 }
211
endSession()212 void sqlrbindvariabletranslations::endSession() {
213 for (singlylinkedlistnode< sqlrbindvariabletranslationplugin * > *node=
214 pvt->_tlist.getFirst();
215 node; node=node->getNext()) {
216 node->getValue()->bvtr->endSession();
217 }
218 }
219