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