⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isql++.cpp.svn-base

📁 絲路server源碼 Silk Road server source
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
/*    This file is part of libodbc++.      Copyright (C) 1999-2000 Manush Dodunekov <manush@stendahls.net>      This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Library General Public   License as published by the Free Software Foundation; either   version 2 of the License, or (at your option) any later version.      This library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Library General Public License for more details.      You should have received a copy of the GNU Library General Public License   along with this library; see the file COPYING.  If not, write to   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA.*/#include "isql++.h"#include <cstdlib>#include <cstdio>#include <iostream>extern "C" {#if defined(ODBCXX_DISABLE_READLINE_HACK)#include <readline/readline.h>#include <readline/history.h>#else  /* readline.h doesn't contain proper function prototypes, which makes     newer gcc versions (>=2.95) barf with certain flags. This could     help the situation.  */  extern char* rl_readline_name;    typedef char** (*CPPFunction)(char*,char*);    extern CPPFunction rl_completion_entry_function;  extern int rl_initialize(void);  extern char* readline(const char*);  extern void add_history(const char*);#ifdef SPACE#undef SPACE#endif#define SPACE ' '#endif}using namespace odbc;using namespace std;const char* SQLPROMPT1="SQL> ";const char* SQLPROMPT2="  +> ";const char* BLOB_FIELD="<BLOB>";const char* NULL_FIELD="<NULL>";const char* INNER_SEPARATOR=" ";const char* OUTER_SEPARATOR=" ";const char SPACE_CHAR=' ';const char LINE_CHAR='=';const char END_OF_STATEMENT=';';const char* WS=" \r\n\t";const int LONGVARCHAR_WIDTH=20;const int MIN_COL_WIDTH_ON_SCREEN=4;// this effectively disables filename completion// with readlinestatic char **noCompletion (char *,char*){  // no completion of filenames  return (char**)NULL;}static const char* getTypeName(int sqlType) {  static struct {    int id;    const char* name;  } sqlTypes[] = {    { Types::BIGINT,		"BIGINT" },    { Types::BINARY,		"BINARY" },    { Types::BIT,		"BIT" },    { Types::CHAR,		"CHAR" },    { Types::DATE,		"DATE" },    { Types::DECIMAL,		"DECIMAL" },    { Types::DOUBLE, 		"DOUBLE" },    { Types::FLOAT,		"FLOAT" },    { Types::INTEGER,		"INTEGER" },    { Types::LONGVARBINARY, 	"LONGVARBINARY" },    { Types::LONGVARCHAR, 	"LONGVARCHAR" },    { Types::NUMERIC, 	"NUMERIC" },    { Types::REAL,		"REAL" },    { Types::SMALLINT,	"SMALLINT" },    { Types::TIME,		"TIME" },    { Types::TIMESTAMP,	"TIMESTAMP" },    { Types::TINYINT,		"TINYINT" },    { Types::VARBINARY, 	"VARBINARY" },    { Types::VARCHAR, 	"VARCHAR" },    {0,			NULL }  };    for(unsigned int i=0; sqlTypes[i].name!=NULL; i++) {    if(sqlTypes[i].id==sqlType) {      return sqlTypes[i].name;    }  }    return "UNKNOWN";}// split string on any of scharsinline vector<string> splitString(const string& str, const char* schars){  vector<string> res;    if(str.length()==0) {    return res;  }  if(strlen(schars)==0) {    res.push_back(str);    return res;  }    string::size_type e=0;  string::size_type s=str.find_first_not_of(schars);    while(s!=string::npos) {    e=str.find_first_of(schars,s);    if(e==string::npos) {      res.push_back(str.substr(s));    } else {      res.push_back(str.substr(s,e-s));    }    s=str.find_first_not_of(schars,e);  }  for(vector<string>::iterator i=res.begin();      i!=res.end(); i++) {  }  return res;}// lowercase a stringinline string toLowerCase(const string& str) {  string ret;    if(str.length()>0) {    ret.resize(str.length());    for(int i=0; i<str.length(); i++) {      ret[i]=tolower(str[i]);    }  }  return ret;}inline string toUpperCase(const string& str) {  string ret;    if(str.length()>0) {      ret.resize(str.length());      for(int i=0; i<str.length(); i++) {	ret[i]=toupper(str[i]);      }  }  return ret;}// split a fully qualified sql table or procedure// identifier into catalog,schema and name// returns a vector of all three of themvoid Isql::splitIdentifier(const string& id,			   string& catalog,			   string& schema,			   string& name){  vector<string> ret;  DatabaseMetaData* md=con_->getMetaData();  string str=id; //local copy, we are going to modify it  if(supportsCatalogs_) {    string catSep=md->getCatalogSeparator();    string::size_type catStart, catEnd;    if(md->isCatalogAtStart()) {      catStart=0;      catEnd=str.find(catSep);      if(catEnd!=string::npos) {	catalog=str.substr(0,catEnd);	str=str.substr(catEnd+catSep.length());      }    } else {      catStart=str.rfind(catSep);      if(catStart!=string::npos) {	catalog=str.substr(catStart+1);	str=str.substr(0,catStart);      }    }  } else {    catalog="";  }  // check for schemas  if(supportsSchemas_) {    string schemaSep=".";        string::size_type schemaEnd=str.find(schemaSep);    if(schemaEnd!=string::npos) {      schema=str.substr(0,schemaEnd);      str=str.substr(schemaEnd+schemaSep.length());    }  } else {    schema="";  }  name=str;  //now, check if we are to perform some case-transforms on this  //since some drivers can't refer to table test using TEST  //when metadata information is requested    if(md->storesLowerCaseIdentifiers()) {    name=toLowerCase(name);    schema=toLowerCase(schema);    catalog=toLowerCase(catalog);  } else if(md->storesUpperCaseIdentifiers()) {    name=toUpperCase(name);    schema=toUpperCase(schema);    catalog=toUpperCase(catalog);  }  //otherwise, we don't touch them}string Isql::makeIdentifier(const string& cat,			    const string& schema,			    const string& name){  string id=name;  DatabaseMetaData* md=con_->getMetaData();  if(supportsSchemas_ && schema.length()>0) {    string schemaSep=".";    id=schema+schemaSep+id;  }  if(supportsCatalogs_ && cat.length()>0) {    string catSep=md->getCatalogSeparator();    if(md->isCatalogAtStart()) {      id=cat+catSep+id;    } else {      id+=(catSep+cat);    }  }  return id;}Isql::Isql(Connection* con)  :con_(con),termWidth_(80),   maxRows_(0){  rl_readline_name="isqlxx";  rl_completion_entry_function=(CPPFunction)noCompletion;  rl_initialize();  commands_["set"]=&Isql::setCmd;  commands_["show"]=&Isql::showCmd;  commands_["commit"]=&Isql::commitCmd;  commands_["rollback"]=&Isql::rollbackCmd;  commands_["describe"]=&Isql::describeCmd;  // a cheap way to check if this supports schemas  try {    ResultSet* rs=con_->getMetaData()->getSchemas();    Deleter<ResultSet> _rs(rs);    supportsSchemas_=rs->next();  } catch(SQLException& e) {    supportsSchemas_=true;  }  // another cheap trick  try {    ResultSet* rs=con_->getMetaData()->getCatalogs();    Deleter<ResultSet> _rs(rs);    supportsCatalogs_=rs->next();  } catch(SQLException& e) {    supportsCatalogs_=true;  }}Isql::~Isql(){  //safety  if(con_->getMetaData()->supportsTransactions()) {    con_->rollback();  }}bool Isql::readInput(string& out){  const char* prompt=(buffer_.length()>0?SQLPROMPT2:SQLPROMPT1);  char* s=readline(prompt);    if(s!=NULL) {        if(s[0]!=0) {      add_history(s);      out=s;    } else {      out = "";    }    //free it (it is malloced)    free(s);    return true;  } else {    return false;  }}void Isql::run(){  string input;    while(this->readInput(input)) {    buffer_=buffer_+(buffer_.length()>0?"\n"+input:input);    string s;    StatementType st=this->extractStatement(s);        switch(st) {    case STATEMENT_SQL:      try {	if(s.length()>1 && 	   s[0]=='"' && s[s.length()-1]=='"') {	  //the whole thing is quoted, strip the quotes	  s=s.substr(1,s.length()-2);	}	PreparedStatement* pstmt=con_->prepareStatement(s);	Deleter<PreparedStatement> _pstmt(pstmt);	//apply maxrows if needed	if(maxRows_>0) {	  pstmt->setMaxRows(maxRows_);	}	this->execute(pstmt);      } catch(SQLException& e) {	cout << e.getMessage() << endl;      }      break;    case STATEMENT_COMMAND:      try {	this->executeCommand(s);      } catch(exception& e) {	cout << e.what() << endl;      }      break;    case STATEMENT_NONE:      break;    }  }}void Isql::execute(PreparedStatement* pstmt){  if(pstmt->execute()) {    ResultSet* rs=pstmt->getResultSet();    Deleter<ResultSet> _rs(rs);    this->printResultSet(rs);  }  try {    int ar=pstmt->getUpdateCount();    cout << OUTER_SEPARATOR << ar << " rows affected" << flush;  } catch(SQLException& e) {} //ignore it  cout << endl;}void Isql::printResultSet(ResultSet* rs){  int cnt=0;    ResultSetMetaData* md=rs->getMetaData();    int totalWidth=0, shrinkableWidth=0;  vector<int> widths;  for(int i=1; i<=md->getColumnCount(); i++) {    int l;    switch(md->getColumnType(i)) {    case Types::LONGVARCHAR:      l=LONGVARCHAR_WIDTH;      break;    case Types::LONGVARBINARY:      l=strlen(BLOB_FIELD);      break;    default:      l=md->getColumnDisplaySize(i);      break;    }    widths.push_back(l);    totalWidth+=l;    if ( i > 1 ) totalWidth += strlen(INNER_SEPARATOR);  }  totalWidth += 2 * strlen(OUTER_SEPARATOR);    if(totalWidth>(int)termWidth_) {    //we'll need to shrink some column widths    //we only do that on char and varchar columns        for(int i=1; i<=md->getColumnCount(); i++) {      switch(md->getColumnType(i)) {      case Types::CHAR:      case Types::VARCHAR:        shrinkableWidth+=md->getColumnDisplaySize(i);        break;      default:        break;      }    }        if(shrinkableWidth>0) {      //ok, now try shrinking      float shrinkFactor = (1.0 - ((float)(totalWidth - (int)termWidth_)) / (float)shrinkableWidth);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -