1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 ***************************************************************************/
18 #include <DatabaseManagerImpl.h>
19 #include <Statement.h>
20 #include <SqlFactory.h>
21 #include <SqlStatement.h>
22 #include <SqlNwConnection.h>
23 #include <SqlNwStatement.h>
24 #ifndef NO_READLINE_LIB
25 #include <readline/readline.h>
26 #include <readline/history.h>
28 #include <NanoTimer.h>
29 #define SQL_STMT_LEN 8192
30 void printVariables();
39 STATEMENT_TYPE stmtType
= SELECT
;
41 AbsSqlConnection
*conn
;
42 AbsSqlStatement
*stmt
;
43 AbsSqlStatement
*aconStmt
; //stmt object when autocommit is on
45 SqlApiImplType type
= CSqlUnknown
;
46 bool gateway
=false, silent
=false;
47 bool autocommitmode
= true;
50 bool firstPrepare
= true;
51 IsolationLevel isoLevel
= READ_COMMITTED
;
56 printf("Usage: csql [ [-u username] [-p passwd] ] [ [-H hostname] [-P port] ]\n");
57 printf(" [-s sqlfile] \n");
58 printf(" username -> username to connect to database\n");
59 printf(" password -> password to connect to database\n");
60 printf(" hostname -> hostname to connect to database through network\n");
61 printf(" port -> port no\n");
62 printf(" sqlfile -> filename containing sql statements\n");
68 int getConnType(int opt
);
70 int main(int argc
, char **argv
)
72 char username
[IDENTIFIER_LENGTH
];
74 char password
[IDENTIFIER_LENGTH
];
76 char hostname
[IDENTIFIER_LENGTH
];
84 while ((c
= getopt(argc
, argv
, "u:p:s:o:H:P:gXUS?")) != EOF
)
88 case 'u' : strcpy(username
, argv
[optind
- 1]); break;
89 case 'p' : strcpy(password
, argv
[optind
- 1]); break;
90 case 's' : strcpy(filename
, argv
[optind
- 1]); break;
91 case 'o' : { connOpt
= atoi(argv
[optind
- 1]); break; }
92 case '?' : { opt
= 1; break; } //print help
93 case 'S' : { silent
= true; break; } //silent
94 case 'X' : { silent
= true; exclusive
= true; break; } //silent
95 case 'g' : { gateway
= true; break; } //print help
96 case 'U' : { noUndolog
= true; break; } //print help
97 case 'H' : { strcpy (hostname
, argv
[optind
- 1]);
98 network
= true; break; }
99 case 'P' : { strcpy (port
, argv
[optind
- 1]);
100 network
= true; break; }
101 default: printf("Wrong args\n"); exit(1);
105 //printf("%s %s %s", username, password, filename);
111 if (username
[0] == '\0' )
113 strcpy(username
, I_USER
);
114 strcpy(password
, I_PASS
);
117 if (hostname
[0] == '\0') { printUsage(); return 0; }
118 if (port
[0] == '\0') { printUsage(); return 0; }
120 bool fileFlag
= false;
121 if (filename
[0] !='\0')
123 fp
= fopen(filename
,"r");
126 printf("Unable to open the file %s\n", filename
);
135 type
= (SqlApiImplType
) getConnType(connOpt
);
136 conn
= SqlFactory::createConnection((SqlApiImplType
)type
);
137 if(connOpt
== 4 || connOpt
== 5 || connOpt
== 6) {
138 SqlNwConnection
*con
= (SqlNwConnection
*)conn
;
139 con
->setHost("localhost", 5678);
141 else if (connOpt
== 7)
142 conn
= SqlFactory::createConnection((SqlApiImplType
)type
);
145 if (gateway
) type
= CSqlNetworkGateway
;
146 else type
= CSqlNetwork
;
147 conn
= SqlFactory::createConnection(type
);
148 SqlNwConnection
*con
= (SqlNwConnection
*)conn
;
149 con
->setHost(hostname
, atoi(port
));
152 if (gateway
) type
= CSqlGateway
;
154 if (exclusive
) type
=CSqlDirect
; else type
= CSql
;
156 conn
= SqlFactory::createConnection(type
);
159 rv
= conn
->connect(username
,password
);
160 if (rv
!= OK
) return 1;
162 SqlConnection
*sCon
= (SqlConnection
*) conn
;
163 rv
= sCon
->getExclusiveLock();
170 aconStmt
= SqlFactory::createStatement(type
);
172 SqlStatement *sqlStmt = (SqlStatement*)aconStmt;
173 sqlStmt->setLoading(true);
175 aconStmt
->setConnection(conn
);
176 //rv = conn->beginTrans(READ_COMMITTED, TSYNC);
177 rv
= conn
->beginTrans();
178 if (rv
!= OK
) return 2;
179 while (getInput(fileFlag
) == true) continue;
181 //TODO::conn should provide method telling status of the transaction.
182 //if running, then abort it
184 if (filename
[0] !='\0')
193 bool handleTransaction(char *st
)
195 while (isspace (*st
)|| *st
== '(' ) st
++; // Skip white spaces
196 if (strcasecmp (st
, "COMMIT;") == 0 ||
197 strcasecmp (st
, "commit;") == 0 )
200 ListIterator it
= sqlStmtList
.getIterator();
201 while(it
.hasElement()) {
202 stmt
= (AbsSqlStatement
*) it
.nextElement();
207 //conn->beginTrans(isoLevel, TSYNC);
208 conn
->beginTrans(isoLevel
);
211 else if (strcasecmp (st
, "ROLLBACK;") == 0||
212 strcasecmp (st
, "rollback;") == 0)
215 ListIterator it
= sqlStmtList
.getIterator();
216 while(it
.hasElement()) {
217 stmt
= (AbsSqlStatement
*)it
.nextElement();
222 //conn->beginTrans(isoLevel, TSYNC);
223 conn
->beginTrans(isoLevel
);
226 else if (strcasecmp (st
, "SET AUTOCOMMIT ON;") == 0)
228 autocommitmode
= true;
229 if (!silent
) printf("AUTOCOMMIT Mode is set to ON\n");
232 else if (strcasecmp (st
, "SET AUTOCOMMIT OFF;") == 0)
234 autocommitmode
= false;
235 if (!silent
) printf("AUTOCOMMIT Mode is set to OFF\n");
238 else if (strcasecmp (st
, "SET ISOLATION LEVEL UNCOMMITTED;") == 0)
240 isoLevel
= READ_UNCOMMITTED
;
241 printf("Isolation Level is set to READ_UNCOMMITTED\n");
244 else if (strcasecmp (st
, "SET ISOLATION LEVEL COMMITTED;") == 0)
246 isoLevel
= READ_COMMITTED
;
247 printf("Isolation Level is set to READ_COMMITTED\n");
250 else if (strcasecmp (st
, "SET ISOLATION LEVEL REPEATABLE;") == 0)
252 isoLevel
= READ_REPEATABLE
;
253 printf("Isolation Level is set to READ_REPEATABLE\n");
256 else if (strcasecmp(st
, "SET TIMER ON;") == 0)
257 { isTimer
=true; return true; }
258 else if (strcasecmp(st
, "SET TIMER OFF;") == 0)
259 { isTimer
=false; return true; }
262 bool handleEchoAndComment(char *st
)
264 while (isspace (*st
)|| *st
== '(' ) st
++; // Skip white spaces
265 if (strncasecmp (st
, "ECHO", 4) == 0)
269 }else if (strncmp(st
, "--", 2) == 0)
272 }else if (strncasecmp(st
, "help", 2) == 0)
276 }else if(strcasecmp(st
,"show variables;")==0){
280 }else if (strcasecmp(st
, "show tables;") == 0) {
282 List tableList
= aconStmt
->getAllTableNames(rv
);
283 ListIterator iter
= tableList
.getIterator();
284 Identifier
*elem
= NULL
;
286 printf("=============TableNames===================\n");
288 while (iter
.hasElement())
290 elem
= (Identifier
*) iter
.nextElement();
292 printf(" %s \n", elem
->name
);
294 if (count
==0) printf(" No tables exist\n");
295 printf("==========================================\n");
297 }else if( strcasecmp(st
, "show users;" )==0){
299 List userList
= aconStmt
->getAllUserNames(rv
);
300 ListIterator iter
= userList
.getIterator();
301 Identifier
*elem
= NULL
;
303 printf("=============UserNames===================\n");
304 while (iter
.hasElement())
306 elem
= (Identifier
*) iter
.nextElement();
307 if(0==strcmp( elem
->name
,I_USER
))
309 printf(" %s \n", elem
->name
);
311 printf("=========================================\n");
318 printf("CSQL Command List\n");
319 printf("======================================================\n");
320 printf("SHOW TABLES\n");
321 printf("SET AUTOCOMMIT ON | OFF\n");
322 printf("COMMIT | ROLLBACK\n");
323 printf("SET ISOLATION LEVEL UNCOMMITTED | COMMITTED | REPEATABLE\n");
324 printf("CREATE TABLE | INDEX ...\n");
325 printf("DROP TABLE | INDEX ...\n");
326 printf("INSERT ...\n");
327 printf("UPDATE ...\n");
328 printf("DELETE ...\n");
329 printf("SELECT ...\n");
331 printf("======================================================\n");
333 void printVariables()
335 //SERVER Section Info.
336 printf("=======================================================\n");
337 printf("| SERVER SECTION INFORMATION |\n");
338 printf("=======================================================\n");
339 printf(" SITE_ID\t\t\t= %d\n",Conf::config
.getSiteID());
340 printf(" PAGE_SIZE\t\t\t= %d Byte\n",Conf::config
.getPageSize());
341 printf(" MAX_PROCS\t\t\t= %d\n",Conf::config
.getMaxProcs());
342 printf(" MAX_SYS_DB_SIZE\t\t= %d MB\n",(Conf::config
.getMaxSysDbSize()/1048576));
343 printf(" MAX_DB_SIZE\t\t\t= %d MB\n",(Conf::config
.getMaxDbSize()/1048576));
344 printf(" SYS_DB_KEY\t\t\t= %d\n",Conf::config
.getSysDbKey());
345 printf(" USER_DB_KEY\t\t\t= %d\n",Conf::config
.getUserDbKey());
346 printf(" LOG_LEVEL\t\t\t= %d\n",Conf::config
.getLogLevel());
347 printf(" MAP_ADDRESS\t\t\t= %ld\n",Conf::config
.getMapAddress());
349 if(Conf::config
.useDurability())
350 printf(" DURABILITY\t\t\t= True\n");
352 printf(" DURABILITY\t\t\t= False\n");
354 if(Conf::config
.useMmap())
355 printf(" MMAP\t\t\t\t= True\n");
357 printf(" MMAP\t\t\t\t= False\n");
359 printf(" DURABLE_MODE\t\t\t= %d\n",Conf::config
.getDurableMode());
360 printf(" DATABASE_FILE\t\t\t= %s\n",Conf::config
.getDbFile());
361 printf(" LOG_FILE_PATH\t\t\t= %s\n",Conf::config
.getLogFile());
362 printf(" STDERR_FILE\t\t\t= %s\n",Conf::config
.getStderrFile());
364 //Network Section Information
365 printf("=======================================================\n");
366 printf("| NETWORK SECTION INFORMATION |\n");
367 printf("=======================================================\n");
369 if(Conf::config
.useCsqlSqlServer())
370 printf(" CSQL_SQL_SERVER\t\t= True\n");
372 printf(" CSQL_SQL_SERVER\t\t= False\n");
374 printf(" PORT\t\t\t\t= %d\n",Conf::config
. getPort());
375 printf(" NETWORK_RESPONSE_TIMEOUT\t= %d\n",Conf::config
.getNetworkResponseTimeout());
376 printf(" NETWORK_CONNECT_TIMEOUT\t= %d\n",Conf::config
.getNetworkConnectTimeout());
377 printf(" ID_SHM_KEY\t\t\t= %d\n",Conf::config
.getShmIDKey());
379 //Client section variables
380 printf("=======================================================\n");
381 printf("| CLIENT SECTION INFORMATION |\n");
382 printf("=======================================================\n");
383 printf(" MUTEX_TIMEOUT_SECS\t\t= %d\n",Conf::config
.getMutexSecs());
384 printf(" MUTEX_TIMEOUT_USECS\t\t= %d\n",Conf::config
.getMutexUSecs());
385 printf(" MUTEX_TIMEOUT_RETRIES\t\t= %d\n",Conf::config
.getMutexRetries());
386 printf(" LOCK_TIMEOUT_SECS\t\t= %d\n",Conf::config
.getLockSecs());
387 printf(" LOCK_TIMEOUT_USECS\t\t= %d\n",Conf::config
.getLockUSecs());
388 printf(" LOCK_TIMEOUT_RETRIES\t\t= %d\n",Conf::config
.getLockRetries());
390 //CACHE Section variables
391 printf("=======================================================\n");
392 printf("| CACHE SECTION INFORMATION |\n");
393 printf("=======================================================\n");
395 if(Conf::config
.useCache())
396 printf(" CACHE_TABLE\t\t\t= True\n");
398 printf(" CACHE_TABLE\t\t\t= False\n");
400 printf(" DSN\t\t\t\t= %s\n",Conf::config
.getDSN());
402 if(Conf::config
.useTwoWayCache())
403 printf(" ENABLE_BIDIRECTIONAL_CACHE\t= True\n");
405 printf(" ENABLE_BIDIRECTIONAL_CACHE\t= False\n");
407 printf(" CACHE_RECEIVER_WAIT_SECS\t= %d\n",Conf::config
.getCacheWaitSecs());
409 if(Conf::config
.getCacheMode()==0)
410 printf(" CACHE_MODE\t\t\t= SYNC\n");
411 else if (Conf::config
.getCacheMode()==1)
412 printf(" CACHE_MODE\t\t\t= ASYNC\n");
414 printf(" CACHE_MODE\t\t\t= Unknown\n");
416 printf(" DS_CONFIG_FILE\t\t\t= %s\n",Conf::config
.getDsConfigFile());
417 printf(" TABLE_CONFIG_FILE\t\t= %s\n",Conf::config
.getTableConfigFile());
418 printf(" MSG_KEY\t\t\t= %d\n",Conf::config
.getMsgKey() );
419 printf(" ASYNC_MSGMAX\t\t\t= %d\n",Conf::config
.getAsyncMsgMax());
420 printf(" MAX_QUEUE_LOGS\t\t\t= %d\n",Conf::config
.getLogLevel());
421 printf(" CONFL_RESOL_FILE\t\t= %s\n",Conf::config
.getConflResoFile());
422 printf(" \nNOTE: To modify above variables, You will be following 'csql.conf' file.\n\n");
425 void setStmtType(char *st
)
427 if (strncasecmp (st
, "SELECT", 6) == 0) {stmtType
=SELECT
; return; }
428 else if (strncasecmp (st
, "EXPLAIN", 6) == 0) {stmtType
=EXPLAIN
; return; }
429 else if (strncasecmp (st
, "CREATE", 6) == 0) {stmtType
=DDL
; return; }
430 else if (strncasecmp (st
, "DROP", 4) == 0) { stmtType
=DDL
; return; }
435 char getQueryFromStdIn(char *buf
)
437 char c
, *bufBegin
=buf
;
439 #ifdef NO_READLINE_LIB
442 while( (c
=(char ) getchar()) != EOF
&& c
!= ';')
444 *buf
++ = c
; charCnt
++;
445 if(c
=='\n') //printf("%1d>",ln++);
447 if( charCnt
== SQL_STMT_LEN
) {
448 printf("SQL Statement length is greater than %d. "
449 "Ignoring the statement.\n", SQL_STMT_LEN
);
454 //printf("=%d=\n", c);
460 char *line
= readline("CSQL>");
461 if (line
) {strcpy(buf
, line
); add_history(line
); }
462 else { free(line
); return EOF
; }
467 char getQueryFromFile(char *buf
)
469 char c
, *bufBegin
=buf
;
471 while( (c
=(char ) fgetc(fp
)) != EOF
&& c
!= ';')
473 *buf
++ = c
; charCnt
++;
474 if( charCnt
== SQL_STMT_LEN
) {
475 printf("SQL Statement length is greater than %d. "
476 "Ignoring the statement.\n", SQL_STMT_LEN
);
487 bool getInput(bool fromFile
)
489 char buffer
[SQL_STMT_LEN
+ 1];
492 if (fromFile
== false)
493 eof
= getQueryFromStdIn(buffer
);
495 eof
= getQueryFromFile(buffer
);
498 while(*buf
== ' ' || *buf
== '\t' || *buf
== '\n') buf
++;
499 if (eof
== EOF
|| strncasecmp (buf
, "quit", 4) == 0)
501 if (handleTransaction(buf
)) return true;
502 if (handleEchoAndComment(buf
)) return true;
503 if ( *buf
== ';' ) return true; // Null statement.
508 if (autocommitmode
) {
509 if (!firstPrepare
) aconStmt
->free();
510 rv
= aconStmt
->prepare(buf
);
512 printf("Statement prepare failed with error %d\n", rv
);
515 firstPrepare
= false;
519 stmt
= SqlFactory::createStatement(type
);
520 stmt
->setConnection(conn
);
521 rv
= stmt
->prepare(buf
);
523 printf("Statement prepare failed with error %d\n", rv
);
526 sqlStmtList
.append(stmt
);
528 if (noUndolog
|| exclusive
){
529 SqlStatement
*sqlStmt
= (SqlStatement
*)stmt
;
530 sqlStmt
->setLoading(true);
534 rv
= stmt
->execute(rows
);
537 printf("Statement execute failed with error %d\n", rv
);
538 if (autocommitmode
) {
541 firstPrepare
= true; //set this so that it does not free again
542 conn
->beginTrans(isoLevel
);
546 sqlStmtList
.remove(stmt
);
547 delete stmt
; stmt
= NULL
;
552 if (stmtType
== EXPLAIN
)
556 else if (stmtType
== OTHER
&& stmt
->isSelect()) stmtType
= SELECT
;
557 else if (stmtType
== OTHER
)
559 if (!silent
) printf("Statement Executed: Rows Affected = %d\n", rows
);
561 else if (stmtType
== DDL
)
563 if (!silent
) printf("Statement Executed\n");
567 FieldInfo
*info
= new FieldInfo();
568 printf("---------------------------------------------------------\n");
570 for (int i
= 0 ; i
< stmt
->noOfProjFields() ; i
++)
572 stmt
->getProjFldInfo(i
+1, info
);
573 printf("%s\t", info
->fldName
);
575 printf("\n---------------------------------------------------------\n");
582 tuple
= (char*)stmt
->fetchAndPrint(false);
584 if (tuple
== NULL
) { break; }
589 if (isTimer
) printf("Time taken: %lld microsecs\n", timer
.sum()/1000);
593 //conn->beginTrans(isoLevel, TSYNC);
595 firstPrepare
= true; //set this so that it does not free again
596 conn
->beginTrans(isoLevel
);
602 int getConnType(int opt
)
605 case 1: { printf("Local CSql\n"); return (int) CSql
; }
606 case 2: { printf("Local Adapter\n"); return (int) CSqlAdapter
; }
607 case 3: { printf("Local Gateway\n"); return (int) CSqlGateway
; }
608 case 4: { printf("Network CSql\n"); return (int) CSqlNetwork
; }
609 case 5: { printf("Network Adapter\n"); return (int) CSqlNetworkAdapter
;}
610 case 6: { printf("Network Gateway\n"); return (int) CSqlNetworkGateway
;}
611 case 7: { printf("Log\n"); return (int) CSqlLog
; }
612 case 8: { printf("Log\n"); return (int) CSqlLog
; }