1 // Copyright (c) 1999-2018 David Muse
2 // See the file COPYING for more information
3
4 #include <sqlrelay/sqlrserver.h>
5 #include <rudiments/charstring.h>
6 #include <rudiments/process.h>
7 #include <rudiments/datetime.h>
8 //#define DEBUG_MESSAGES 1
9 #include <rudiments/debugprint.h>
10 #include <datatypes.h>
11
12 class SQLRSERVER_DLLSPEC sqlrquery_sqlrcmdcstat : public sqlrquery {
13 public:
14 sqlrquery_sqlrcmdcstat(sqlrservercontroller *cont,
15 sqlrqueries *qs,
16 domnode *parameters);
17 bool match(const char *querystring, uint32_t querylength);
18 sqlrquerycursor *newCursor(sqlrserverconnection *conn,
19 uint16_t id);
20 };
21
22 class sqlrquery_sqlrcmdcstatcursor : public sqlrquerycursor {
23 public:
24 sqlrquery_sqlrcmdcstatcursor(
25 sqlrserverconnection *sqlrcon,
26 sqlrquery *q,
27 domnode *parameters,
28 uint16_t id);
29 ~sqlrquery_sqlrcmdcstatcursor();
30
31 bool executeQuery(const char *query,
32 uint32_t length);
33 uint32_t colCount();
34 const char *getColumnName(uint32_t col);
35 uint16_t getColumnType(uint32_t col);
36 uint32_t getColumnLength(uint32_t col);
37 uint32_t getColumnPrecision(uint32_t col);
38 uint32_t getColumnScale(uint32_t col);
39 uint16_t getColumnIsNullable(uint32_t col);
40 bool noRowsToReturn();
41 bool fetchRow(bool *error);
42 void getField(uint32_t col,
43 const char **field,
44 uint64_t *fieldlength,
45 bool *blob, bool *null);
46 private:
47 uint64_t currentrow;
48 char *fieldbuffer[9];
49
50 sqlrconnstatistics *cs;
51
52 };
53
sqlrquery_sqlrcmdcstat(sqlrservercontroller * cont,sqlrqueries * qs,domnode * parameters)54 sqlrquery_sqlrcmdcstat::sqlrquery_sqlrcmdcstat(sqlrservercontroller *cont,
55 sqlrqueries *qs,
56 domnode *parameters) :
57 sqlrquery(cont,qs,parameters) {
58 debugFunction();
59 }
60
match(const char * querystring,uint32_t querylength)61 bool sqlrquery_sqlrcmdcstat::match(const char *querystring,
62 uint32_t querylength) {
63 debugFunction();
64 return !charstring::compareIgnoringCase(querystring,"sqlrcmd cstat");
65 }
66
newCursor(sqlrserverconnection * sqlrcon,uint16_t id)67 sqlrquerycursor *sqlrquery_sqlrcmdcstat::newCursor(
68 sqlrserverconnection *sqlrcon,
69 uint16_t id) {
70 return new sqlrquery_sqlrcmdcstatcursor(sqlrcon,this,
71 getParameters(),id);
72 }
73
sqlrquery_sqlrcmdcstatcursor(sqlrserverconnection * sqlrcon,sqlrquery * q,domnode * parameters,uint16_t id)74 sqlrquery_sqlrcmdcstatcursor::sqlrquery_sqlrcmdcstatcursor(
75 sqlrserverconnection *sqlrcon,
76 sqlrquery *q,
77 domnode *parameters,
78 uint16_t id) :
79 sqlrquerycursor(sqlrcon,q,parameters,id) {
80 currentrow=0;
81 for (uint16_t i=0; i<9; i++) {
82 fieldbuffer[i]=NULL;
83 }
84 cs=NULL;
85 }
86
~sqlrquery_sqlrcmdcstatcursor()87 sqlrquery_sqlrcmdcstatcursor::~sqlrquery_sqlrcmdcstatcursor() {
88 for (uint16_t i=0; i<9; i++) {
89 delete[] fieldbuffer[i];
90 }
91 }
92
executeQuery(const char * query,uint32_t length)93 bool sqlrquery_sqlrcmdcstatcursor::executeQuery(const char *query,
94 uint32_t length) {
95 currentrow=0;
96 return true;
97 }
98
colCount()99 uint32_t sqlrquery_sqlrcmdcstatcursor::colCount() {
100 return 9;
101 }
102
103 struct colinfo_t {
104 const char *name;
105 uint16_t type;
106 uint32_t length;
107 uint32_t precision;
108 uint32_t scale;
109 };
110
111 static struct colinfo_t colinfo[]={
112 {"INDEX",NUMBER_DATATYPE,10,10,0},
113 {"MINE",VARCHAR2_DATATYPE,1,0,0},
114 {"PROCESSID",NUMBER_DATATYPE,10,10,0},
115 {"CONNECT",NUMBER_DATATYPE,12,12,0},
116 {"STATE",VARCHAR2_DATATYPE,25,0,0},
117 {"STATE_TIME",NUMBER_DATATYPE,12,12,2},
118 {"CLIENT_ADDR",VARCHAR2_DATATYPE,24,0,0},
119 {"CLIENT_INFO",VARCHAR2_DATATYPE,STATCLIENTINFOLEN-1,0,0},
120 {"SQL_TEXT",VARCHAR2_DATATYPE,STATSQLTEXTLEN-1,0,0}
121 };
122
getColumnName(uint32_t col)123 const char *sqlrquery_sqlrcmdcstatcursor::getColumnName(uint32_t col) {
124 return (col<9)?colinfo[col].name:NULL;
125 }
126
getColumnType(uint32_t col)127 uint16_t sqlrquery_sqlrcmdcstatcursor::getColumnType(uint32_t col) {
128 return (col<9)?colinfo[col].type:0;
129 }
130
getColumnLength(uint32_t col)131 uint32_t sqlrquery_sqlrcmdcstatcursor::getColumnLength(uint32_t col) {
132 return (col<9)?colinfo[col].length:0;
133 }
134
getColumnPrecision(uint32_t col)135 uint32_t sqlrquery_sqlrcmdcstatcursor::getColumnPrecision(uint32_t col) {
136 return (col<9)?colinfo[col].precision:0;
137 }
138
getColumnScale(uint32_t col)139 uint32_t sqlrquery_sqlrcmdcstatcursor::getColumnScale(uint32_t col) {
140 return (col<9)?colinfo[col].scale:0;
141 }
142
getColumnIsNullable(uint32_t col)143 uint16_t sqlrquery_sqlrcmdcstatcursor::getColumnIsNullable(uint32_t col) {
144 return (col==7 || col==8)?1:0;
145 }
146
noRowsToReturn()147 bool sqlrquery_sqlrcmdcstatcursor::noRowsToReturn() {
148 return false;
149 }
150
fetchRow(bool * error)151 bool sqlrquery_sqlrcmdcstatcursor::fetchRow(bool *error) {
152 *error=false;
153 while (currentrow<MAXCONNECTIONS) {
154 cs=&(conn->cont->getShm()->connstats[currentrow]);
155 currentrow++;
156 if (cs->processid) {
157 return true;
158 }
159 }
160 return false;
161 }
162
163 static const char * const statenames[]={
164 "NOT_AVAILABLE",
165 "INIT",
166 "WAIT_FOR_AVAIL_DB",
167 "WAIT_CLIENT",
168 "SESSION_START",
169 "GET_COMMAND",
170 "PROCESS_SQL",
171 "PROCESS_SQLCMD",
172 "RETURN_RESULT_SET",
173 "END_SESSION",
174 "ANNOUNCE_AVAILABILITY",
175 "WAIT_SEMAPHORE"
176 };
177
getField(uint32_t col,const char ** field,uint64_t * fieldlength,bool * blob,bool * null)178 void sqlrquery_sqlrcmdcstatcursor::getField(uint32_t col,
179 const char **field,
180 uint64_t *fieldlength,
181 bool *blob,
182 bool *null) {
183 *field=NULL;
184 *fieldlength=0;
185 *blob=false;
186 *null=false;
187
188 delete[] fieldbuffer[col];
189 fieldbuffer[col]=NULL;
190
191 switch (col) {
192 case 0:
193 // index -
194 // index in sqlrshm.connstats array
195 fieldbuffer[col]=charstring::parseNumber(currentrow-1);
196 break;
197 case 1:
198 // mine -
199 // * if the connection is processing this command
200 if (cs->processid==(uint32_t)process::getProcessId()) {
201 *field="*";
202 *fieldlength=1;
203 } else {
204 *null=true;
205 }
206 return;
207 case 2:
208 // processid -
209 // pid of the connection
210 fieldbuffer[col]=charstring::parseNumber(cs->processid);
211 break;
212 case 3:
213 // connect -
214 // number of client connections
215 fieldbuffer[col]=charstring::parseNumber(cs->nconnect);
216 break;
217 case 4:
218 // state -
219 // internally defined status
220 if (cs->state<=WAIT_SEMAPHORE) {
221 *field=statenames[cs->state];
222 *fieldlength=charstring::length(*field);
223 return;
224 }
225 *null=true;
226 return;
227 case 5:
228 {
229 // state_time -
230 // seconds the connection has been in its current state
231 datetime dt;
232 dt.getSystemDateAndTime();
233 double statetime=
234 ((double)(dt.getSeconds()-
235 cs->statestartsec))+
236 ((double)(dt.getMicroseconds()-
237 cs->statestartusec))/1000000.0;
238 fieldbuffer[col]=charstring::parseNumber(statetime,
239 colinfo[5].precision,colinfo[5].scale);
240 }
241 break;
242 case 6:
243 // client_addr -
244 // address of currently connected client
245 *field=cs->clientaddr;
246 *fieldlength=charstring::length(*field);
247 return;
248 case 7:
249 // client info -
250 // client info string
251 *field=cs->clientinfo;
252 *fieldlength=charstring::length(*field);
253 return;
254 case 8:
255 // sql_text -
256 // query currently being executed
257 *field=cs->sqltext;
258 *fieldlength=charstring::length(*field);
259 return;
260 default:
261 *null=true;
262 return;
263 }
264
265 *field=fieldbuffer[col];
266 *fieldlength=charstring::length(fieldbuffer[col]);
267 }
268
269 extern "C" {
new_sqlrquery_sqlrcmdcstat(sqlrservercontroller * cont,sqlrqueries * qs,domnode * parameters)270 SQLRSERVER_DLLSPEC sqlrquery *new_sqlrquery_sqlrcmdcstat(
271 sqlrservercontroller *cont,
272 sqlrqueries *qs,
273 domnode *parameters) {
274 return new sqlrquery_sqlrcmdcstat(cont,qs,parameters);
275 }
276 }
277