From: Andrey C. <sku...@us...> - 2006-06-02 14:32:49
|
Update of /cvsroot/eas-dev/eas/libcodb_query In directory sc8-pr-cvs5.sourceforge.net:/tmp/cvs-serv11504/libcodb_query Added Files: Makefile codb.prg command.prg formatter.prg Log Message: Add files --- NEW FILE: Makefile --- # This is a part of E/AS project # # Copyright (C) 2003-2005 by E/AS Software Foundation # Author: Andrey Cherepanov <sk...@ea...> ifndef CLIPROOT CLIPROOT=$(shell cd ../../../; pwd)/cliproot endif include $(CLIPROOT)/include/Makefile.inc CLIPINCLUDE = -I$(CLIPROOT)/include CLIP = $(CLIPROOT)/bin/clip CLIPLIBS = -L$(CLIPROOT)/lib -lclip-codb CODBLIBS = -lcodb_query .SUFFIXES: .prg .o .po # Here you can define appropriate compile settings #C_FLAGS=-Wall -g -I. $(CLIPINCLUDE) #CC=gcc TARGET = libcodb_query$(DLLSUFF) RTARGET = libcodb_query$(DLLREALSUFF) BIN_TARGET = codb OBJS = command.o formatter.o BIN_OBJS = codb.o .PHONY: all clean uninstall distclean all: $(TARGET) $(TARGET): $(OBJS) $(CLIPROOT)/bin/clip_makeslib $(TARGET) $(OBJS) $(BIN_TARGET): $(BIN_OBJS) $(CLIP) $(CLIPFLAGS) -eslM $(CLIPINCLUDE) -o $(BIN_TARGET) $(BIN_OBJS) $(CLIPLIBS) $(CODBLIBS) clean: rm -f $(OBJS) $(BIN_OBJS) $(TARGET) $(BIN_TARGET) *.bak *.nm *.ex *.ppo *.dll.a *.log *.dll *.so install: all install_lib $(BIN_TARGET) mkdir -p $(DESTDIR)$(CLIPROOT)/bin $(CLIPROOT)/bin/clip_cp $(BIN_TARGET) $(DESTDIR)$(CLIPROOT)/bin install_lib: mkdir -p $(DESTDIR)$(CLIPROOT)/lib $(CLIPROOT)/bin/clip_cp $(TARGET) $(DESTDIR)$(CLIPROOT)/lib $(CLIPROOT)/bin/clip_cp $(RTARGET) $(DESTDIR)$(CLIPROOT)/lib uninstall: rm -f $(CLIPROOT)/lib/$(TARGET) $(CLIPROOT)/lib/$(RTARGET) $(CLIPROOT)/bin/$(BIN_TARGET) distclean: clean dist: distclean .prg.o: $(CLIP) $(CLIPINCLUDE) $< commit: _cvs commit update: _cvs update -dP ucommit: _cvs update -dP && _cvs commit shell: sh --- NEW FILE: codb.prg --- /*-------------------------------------------------------------------------*/ /* This is part of console client for CODB database */ /* */ /* Copyright (C) 2005 by E/AS Software Foundation */ /* Author: Andrey Cherepanov <sk...@ea...> */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by the Free Software Foundation; either version 2 of the */ /* License, or (at your option) any later version. */ /*-------------------------------------------------------------------------*/ #define FILE_BUFFER 4096 static clientVersion := "0.1" static db, dbname:="", fmt /* TODO: - connection string for connect via COBrA server (-u, -p, -s) - exit function for correct connection shutdown - 'set <param>=<mode>' command needed */ /* Main function */ function main(p1) local e, i, h, s:='', ss, params:=array(0), ret set cancel off // Read from pipe h := fopen("-|") while .T. ss := freadstr(h,256) s := s + ss if empty(ss) exit endif end fclose(h) fmt := CODB_Formatter() for i:=1 to pcount() if ascan({'-h','--help','-?'}, param(i)) > 0 printUsage(1) // help return 0 elseif param(i)=='--version' printUsage(2) // version return 0 elseif param(i) == '--hide-titles' fmt:options:hide_titles := .T. elseif left(param(i),8) == "--delim=" fmt:options:delim := substr(param(i),9) elseif left(param(i),1) == '-' .and. param(i) != '-c' ?? "Unknown parameter: "+param(i),chr(10) else aadd(params, param(i)) endif next for i:=1 to len(params) if params[i] == '-c' .and. i < len(params) s := params[i+1] if right(rtrim(s),1) != ';' s += ';' endif adel(params,i) adel(params,i) asize(params,len(params)-2) endif next // TODO: connect if needed db := codb_connect() e := codb_get_error( db ) if e != NIL ?? "ERROR codb_connect(): " + e + chr(10) return 1 endif //?? params, s,chr(10) if len(params) > 0 // Database name // possible use in form DB:DEP params[len(params)] := strtran(params[len(params)], ":", " ") //?? "USE",params[len(params)],";&\n" ret := codb_execute( db, "use "+params[len(params)]+";" ) // Database name change e := codb_get_error( ret ) if e == NIL dbname := codb_get_answer( ret ) else ?? "ERROR: " + e + "&\n" return 1 endif endif if empty(s) printUsage(0) consoleMode() else executeCommand( s ) endif // TODO: correct disconnect from database codb_close( db ) return 0 /* Print usage information */ static function printUsage(mode) // TODO: i18n for printUsage() if mode == 0 // console mode ?? "codb Ver. " + clientVersion + " Console client for CODB database.&\n&\n" ?? "Type 'help' for list of commands or 'quit' for exit&\n&\n" elseif mode == 2 // version ?? clientVersion,"&\n" else // help ?? "codb Ver. " + clientVersion + " Console client for CODB database.&\n" ?? "Copyright (C) 2005 E/AS Software Foundation&\n" ?? "This software comes with ABSOLUTELY NO WARRANTY. This is free software,&\n" ?? "and you are welcome to modify and redistribute it under the GPL license&\n" ?? "&\n" // TODO: full list of command options ?? "Usage: codb [OPTIONS] [dbname[:depository]]&\n&\n" ?? "Options:&\n" ?? " -?, -h, --help Display this help and exit.&\n" ?? " --version Display program version and exit.&\n" ?? " -c 'command' Run command and exit.&\n" ?? " --hide-titles Suppress column names.&\n" ?? " --delim='DELIM' Set columns delimiter.&\n" endif return /* Console mode. Using readline library */ static function consoleMode() local comm:='', ret, prompt, buffer:='', cont:=.F., oErr // TODO: set key '\d' for exit prompt := dbname + "> " oErr := ErrorBlock({|e| break(e) }) while .T. begin sequence ?? prompt ACCEPT TO comm // TODO: Ctrl-C handle! if .not. cont if alltrim(upper(comm)) == 'QUIT' exit elseif upper(comm) == 'HELP' ret := codb_execute( db, comm+";" ) ?? fmt:show( ret ) // TODO: show console specific commands loop endif endif ret := executeCommand(buffer+comm) if empty(ret) prompt := dbname + "> " cont := .F. buffer := '' else // Uncomplete command prompt += iif(dbname!='',replicate('-',len(dbname)),'-') + "> " cont := .T. buffer := ret + ' ' endif recover using oErr ?? "INTERNAL ERROR:", oErr:description+' ('+oErr:fileName+')', chr(10) end sequence enddo return /* Execute command with check delimiters */ static function executeCommand(comm) local i:=0, pos, string:=.F., buffer:='', ret:=NIL, is_filename:=.F. local j, ampos, fileNames:=array(0), files, fH, s, ss local fBuf:=space(FILE_BUFFER), rTotal // ?? 'EXECUTE:',comm,chr(10) while len(comm) > 0 .and. i<=len(comm) i := i + 1 if comm[i]=="'" .and. (i==1 .or. comm[i-1]!='&\\') string := .not. string elseif .not. string .and. .not. is_filename .and. comm[i]=='@' ampos := i is_filename := .T. elseif .not. string .and. is_filename .and. comm[i]=='@' aadd( fileNames, substr(comm, ampos+1, i-ampos-1) ) is_filename := .F. elseif .not. string .and. comm[i]==';' // command end // ?? "EXEC:",left(comm,i-1),chr(10) // Process file names in command files := array(0) for j=1 to len(fileNames) fH := fopen(fileNames[j], 0) s := '' if ferror() == 0 rTotal := 0 while .T. ss := fread(fH, @fBuf, FILE_BUFFER) s := s + left(fBuf, ss) rTotal += ss if ss == 0 exit endif end fclose(fH) //?? "Append file '"+fileNames[j]+"':",rTotal,len(s),chr(10) aadd( files, { fileNames[j], s } ) else ?? "Error opening '"+fileNames[j]+"'.&\n" endif next fileNames := array(0) //?? files,chr(10) ret := codb_execute( db, left(comm,i-1), NIL, files ) ?? fmt:show( ret ) // Database name change if lower(left(comm, 4)) == 'use ' .and. .not. "ERROR" $ ret dbname := ret:answer endif if i<len(comm) comm := substr(comm,i+1) i := 0 else return '' endif endif enddo return comm --- NEW FILE: command.prg --- /*-------------------------------------------------------------------------*/ /* This is part of console client for CODB database */ /* */ /* Copyright (C) 2005 by E/AS Software Foundation */ /* Author: Andrey Cherepanov <sk...@ea...> */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by the Free Software Foundation; either version 2 of the */ /* License, or (at your option) any later version. */ /*-------------------------------------------------------------------------*/ #include <codb_dbf.ch> /** Class for database manipulation in console mode */ /* TODO: - BUG: cannot create EXTENT normally (need close depositories before creation) - WHERE in SELECT statement: translate logical operation and quotes - export/import [...1243 lines suppressed...] endif //?? "got", o, chr(10) for j:=1 to len(attrs) field := attrs[j] if upper(field) $ o value := o[upper(field)] else value := NIL endif row[j] := value next aadd( res:data, row ) next next recover using oErr return "Error select: "+errorMessage(oErr) end sequence return NIL --- NEW FILE: formatter.prg --- /*-------------------------------------------------------------------------*/ /* This is part of console client for CODB database */ /* */ /* Copyright (C) 2005 by E/AS Software Foundation */ /* Author: Andrey Cherepanov <sk...@ea...> */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by the Free Software Foundation; either version 2 of the */ /* License, or (at your option) any later version. */ /*-------------------------------------------------------------------------*/ /** Class for CODB_Result object formatted for show in console */ /* TODO: - --format (text, csv, xml) - use only codb_* functions, not class hack */ #define DEF_DELIMITER ' ' function CODB_Formatter() local obj obj := map() obj:className := "CODB_Formatter" obj:options := map() obj:options:hide_titles := .F. obj:options:delim := DEF_DELIMITER _recover_CODBFORMATTER(obj) return obj function _recover_CODBFORMATTER(obj) obj:show := @c_show() return /* Show formatted output */ static function c_show(self, res) local e, d, s:="", c_len, k, j, total:=0, val, s_val, s_str if valtype(res) != "O" .or. .not. "ANSWER" $ res .or. .not. "DATA" $ res return "ERROR: bad returned object.&\n" endif // Check error e := codb_get_error(res) if e != NIL return "ERROR: " + e + chr(10) endif // Check empty data d := codb_get_result( res ) if d == NIL .or. (valtype(d)=="A" .and. len(d)==0) return "" endif // Generate value length for each columns of data c_len := array(len(d[1])) afill(c_len, 0) for k:=1 to len(d) for j:=1 to len(d[k]) if len(d[k][j]) > c_len[j] c_len[j] := len(d[k][j]) endif next next // Print fields if exists if .not. self:options:hide_titles .and. "FIELDS" $ res .and. valtype(res:fields)=="A" .and. len(res:fields)==len(c_len) for k:=1 to len(res:fields) c_len[k] := iif(c_len[k]<=len(res:fields[k]),len(res:fields[k]),c_len[k]) s += res:fields[k] + space(c_len[k]-len(res:fields[k])) + self:options:delim total += c_len[k] + len(self:options:delim) next s = left(s,len(s)-len(self:options:delim)) + chr(10) + replicate('-', total-len(self:options:delim)) + chr(10) endif // Output data for k:=1 to len(d) s_str := "" for j:=1 to len(d[k]) val := d[k][j] s_val := f_val2str(val) if c_len[j] > len(s_val) s_val := s_val + space(c_len[j]-len(s_val)) endif s_str += s_val + self:options:delim next s += left(s_str,len(s_str)-len(self:options:delim)) + chr(10) next return s /* f_val2str() - convert value to string */ static function f_val2str(val) local i, s_val switch valtype(val) case 'U' s_val := "<NIL>" case 'B' s_val := "<NIL>" case 'C' s_val := val case 'N' s_val := alltrim(str(val)) case 'L' s_val := iif(val,'.T.','.F.') case 'D' s_val := dtoc(val) case 'A' s_val := "{" for i:=1 to len(val) s_val += f_val2str(val[i])+"," next s_val := iif(len(val)>0,left(s_val,len(s_val)-1),s_val)+"}" case 'O' s_val := '<OBJECT>' otherwise s_val := '<UNKNOWN ('+valtype(val)+')='+varToString(val)+">" endswitch return s_val |