Diff for /parser3/src/classes/table.C between versions 1.205 and 1.220

version 1.205, 2004/07/14 08:36:40 version 1.220, 2006/01/20 11:28:44
Line 1 Line 1
 /** @file  /** @file
         Parser: @b table parser class.          Parser: @b table parser class.
   
         Copyright (c) 2001-2004 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
 */  */
   
 static const char * const IDENT_TABLE_C="$Date$";  static const char * const IDENT_TABLE_C="$Date$";
   
 #include "classes.h"  #include "classes.h"
Line 21  static const char * const IDENT_TABLE_C= Line 20  static const char * const IDENT_TABLE_C=
   
 class MTable: public Methoded {  class MTable: public Methoded {
 public: // VStateless_class  public: // VStateless_class
         Value* create_new_value(Pool&) { return new VTable(); }          Value* create_new_value(Pool&, HashStringValue&) { return new VTable(); }
   
 public:  public:
         MTable();          MTable();
Line 37  DECLARE_CLASS_VAR(table, new MTable, 0); Line 36  DECLARE_CLASS_VAR(table, new MTable, 0);
 // defines for globals  // defines for globals
   
 #define SQL_BIND_NAME "bind"  #define SQL_BIND_NAME "bind"
 #define SQL_LIMIT_NAME "limit"  
 #define SQL_OFFSET_NAME "offset"  
 #define SQL_DEFAULT_NAME "default"  #define SQL_DEFAULT_NAME "default"
 #define SQL_DISTINCT_NAME "distinct"  #define SQL_DISTINCT_NAME "distinct"
 #define TABLE_REVERSE_NAME "reverse"  #define TABLE_REVERSE_NAME "reverse"
Line 46  DECLARE_CLASS_VAR(table, new MTable, 0); Line 43  DECLARE_CLASS_VAR(table, new MTable, 0);
 // globals  // globals
   
 String sql_bind_name(SQL_BIND_NAME);  String sql_bind_name(SQL_BIND_NAME);
 String sql_limit_name(SQL_LIMIT_NAME);  String sql_limit_name(PA_SQL_LIMIT_NAME);
 String sql_offset_name(SQL_OFFSET_NAME);  String sql_offset_name(PA_SQL_OFFSET_NAME);
 String sql_default_name(SQL_DEFAULT_NAME);  String sql_default_name(SQL_DEFAULT_NAME);
 String sql_distinct_name(SQL_DISTINCT_NAME);  String sql_distinct_name(SQL_DISTINCT_NAME);
 String table_reverse_name(TABLE_REVERSE_NAME);  String table_reverse_name(TABLE_REVERSE_NAME);
   
 // local defines  
   
 #define COLUMN_SEPARATOR_NAME "separator"  
 #define COLUMN_ENCLOSER_NAME "encloser"  
   
   
 // methods  // methods
   
 static Table::Action_options get_action_options(Request& r, MethodParams& params,   static Table::Action_options get_action_options(Request& r, MethodParams& params, 
Line 73  static Table::Action_options get_action_ Line 64  static Table::Action_options get_action_
         ]          ]
         but there is ^table.locate[name;value]          but there is ^table.locate[name;value]
   
           ...if(voptions.is_defined() && !voptions.is_string()))
         if(maybe_options.is_string()) { // allow empty options          if(maybe_options.is_string()) { // allow empty options
                 result.defined=true;                  result.defined=true;
                 return result;                  return result;
Line 146  static void _create(Request& r, MethodPa Line 138  static void _create(Request& r, MethodPa
         size_t raw_pos_after=0;          size_t raw_pos_after=0;
         Table::columns_type columns;          Table::columns_type columns;
         if(params.count()==2) {          if(params.count()==2) {
                   const String& snameless=params.as_string(0, "called with two params, first param may only be string 'nameless'");
                   if(snameless!="nameless")
                           throw Exception("parser.runtime",
                                   &snameless,
                                   "table::create called with two params, first param may only be 'nameless'");
                 columns=Table::columns_type(0); // nameless                  columns=Table::columns_type(0); // nameless
         } else {          } else {
                 columns=Table::columns_type(new ArrayString);                  columns=Table::columns_type(new ArrayString);
Line 263  static void skip_empty_and_comment_lines Line 260  static void skip_empty_and_comment_lines
 }  }
   
 struct TableSeparators {  struct TableSeparators {
         char column;          char column;  const String* scolumn;
         char encloser;          char encloser; const String* sencloser;
         const String* sencloser;  
           TableSeparators():
         TableSeparators() {                  column('\t'), scolumn(new String("\t", false)),
                 column='\t';                  encloser(0), sencloser(0)
                 encloser=0;          {}
         }          int load( HashStringValue& options ) {
         void load( HashStringValue& options ) {                  int result=0;
                 if(Value* vseparator=options.get(COLUMN_SEPARATOR_NAME)) {                  if(Value* vseparator=options.get(PA_COLUMN_SEPARATOR_NAME)) {
                         options.remove(COLUMN_SEPARATOR_NAME);                          scolumn=&vseparator->as_string();
                         const String& sseparator=vseparator->as_string();                          if(scolumn->length()!=1)
                         if(sseparator.length()!=1)  
                                 throw Exception("parser.runtime",                                  throw Exception("parser.runtime",
                                         &sseparator,                                          scolumn,
                                         "separator must be one character long");                                          "separator must be one character long");
                         column=sseparator.first_char();                          column=scolumn->first_char();
                           result++;
                 }                  }
                 if(Value* vencloser=options.get(COLUMN_ENCLOSER_NAME)) {                  if(Value* vencloser=options.get(PA_COLUMN_ENCLOSER_NAME)) {
                         options.remove(COLUMN_ENCLOSER_NAME);  
                         sencloser=&vencloser->as_string();                          sencloser=&vencloser->as_string();
                         if(sencloser->length()!=1)                          if(sencloser->length()!=1)
                                 throw Exception("parser.runtime",                                  throw Exception("parser.runtime",
                                         sencloser,                                          sencloser,
                                         "encloser must be one character long");                                          "encloser must be one character long");
                         encloser=sencloser->first_char();                          encloser=sencloser->first_char();
                           result++;
                 }                  }
                   return result;
         }          }
 };  };
   
Line 333  static void _load(Request& r, MethodPara Line 331  static void _load(Request& r, MethodPara
         }          }
                   
         Table& table=*new Table(columns);          Table& table=*new Table(columns);
           int columns_count=columns? columns->count(): 0;
   
         // parse cells          // parse cells
         Table::element_type row(new ArrayString);          Table::element_type row(new ArrayString(columns_count));
         skip_empty_and_comment_lines(&data);          skip_empty_and_comment_lines(&data);
         while( lsplit_result sr=lsplit(&data, separators.column, '\n', separators.encloser) ) {          while( lsplit_result sr=lsplit(&data, separators.column, '\n', separators.encloser) ) {
                 if(!*sr.piece && !sr.delim && !row->count()) // append last empty column [if without \n]                  if(!*sr.piece && !sr.delim && !row->count()) // append last empty column [if without \n]
Line 343  static void _load(Request& r, MethodPara Line 342  static void _load(Request& r, MethodPara
                 *row+=new String(sr.piece, 0, true);                  *row+=new String(sr.piece, 0, true);
                 if(sr.delim=='\n') {                  if(sr.delim=='\n') {
                         table+=row;                          table+=row;
                         row=new ArrayString;                          row=new ArrayString(columns_count);
                         skip_empty_and_comment_lines(&data);                          skip_empty_and_comment_lines(&data);
                 }                  }
         }          }
Line 360  static void maybe_enclose( String& to, c Line 359  static void maybe_enclose( String& to, c
                 to<<*sencloser;                  to<<*sencloser;
                 // while we have 'encloser'...                  // while we have 'encloser'...
                 size_t pos_after=0;                  size_t pos_after=0;
                 for( size_t pos_before; (pos_before=from.pos( encloser, pos_after ))!=STRING_NOT_FOUND; pos_after=pos_before+1) {                  for( size_t pos_before; (pos_before=from.pos( encloser, pos_after ))!=STRING_NOT_FOUND; pos_after=pos_before) {
             to<<from.mid(pos_before+1/*+found encloser*/, pos_after-pos_before);                          pos_before++; // including first encloser (and skipping it for next pos)
               to<<from.mid(pos_after, pos_before);
                         to<<*sencloser; // doubling encloser                          to<<*sencloser; // doubling encloser
                 }                  }
                 // last piece                  // last piece
Line 395  static void _save(Request& r, MethodPara Line 395  static void _save(Request& r, MethodPara
         TableSeparators separators;          TableSeparators separators;
         if(param_index<params.count()) {          if(param_index<params.count()) {
                 if(HashStringValue *options=params.as_no_junction(param_index++, "additional params must be hash").get_hash()) {                  if(HashStringValue *options=params.as_no_junction(param_index++, "additional params must be hash").get_hash()) {
                         separators.load(*options);                          int valid_options=separators.load(*options);
                         if(options->count())                          if(valid_options!=options->count())
                                 throw Exception("parser.runtime",                                  throw Exception("parser.runtime",
                                         0,                                          0,
                                         "invalid option passed");                                          "invalid option passed");
Line 419  static void _save(Request& r, MethodPara Line 419  static void _save(Request& r, MethodPara
                         for(Array_iterator<const String*> i(*table.columns()); i.has_next(); ) {                          for(Array_iterator<const String*> i(*table.columns()); i.has_next(); ) {
                                 maybe_enclose( sdata, *i.next(), separators.encloser, separators.sencloser );                                  maybe_enclose( sdata, *i.next(), separators.encloser, separators.sencloser );
                                 if(i.has_next())                                  if(i.has_next())
                                         sdata.append_know_length("\t", 1, String::L_CLEAN);                                          sdata<<*separators.scolumn;
                         }                          }
                 } else { // nameless table [we were asked to output column names]                  } else { // nameless table [we were asked to output column names]
                         if(int lsize=table.count()?table[0]->count():0)                          if(int lsize=table.count()?table[0]->count():0)
Line 427  static void _save(Request& r, MethodPara Line 427  static void _save(Request& r, MethodPara
                                         char *cindex_tab=new(PointerFreeGC) char[MAX_NUMBER];                                          char *cindex_tab=new(PointerFreeGC) char[MAX_NUMBER];
                                         sdata.append_know_length(cindex_tab,                                           sdata.append_know_length(cindex_tab, 
                                                 snprintf(cindex_tab, MAX_NUMBER,                                                   snprintf(cindex_tab, MAX_NUMBER, 
                                                         column<lsize-1?"%d\t":"%d", column),                                                          column<lsize-1?"%d%c":"%d", column, separators.column),
                                                         String::L_CLEAN);                                                          String::L_CLEAN);
                                 }                                  }
                         else                          else
Line 442  static void _save(Request& r, MethodPara Line 442  static void _save(Request& r, MethodPara
                 for(Array_iterator<const String*> c(*i.next()); c.has_next(); ) {                  for(Array_iterator<const String*> c(*i.next()); c.has_next(); ) {
                         maybe_enclose( sdata, *c.next(), separators.encloser, separators.sencloser );                          maybe_enclose( sdata, *c.next(), separators.encloser, separators.sencloser );
                         if(c.has_next())                          if(c.has_next())
                                 sdata.append_know_length("\t", 1, String::L_CLEAN);                                  sdata<<*separators.scolumn;
                 }                  }
                 sdata.append_know_length("\n", 1, String::L_CLEAN);                  sdata.append_know_length("\n", 1, String::L_CLEAN);
         }          }
   
         // write          // write
         file_write(r.absolute(file_name),           {
                 sdata.cstr(), sdata.length(), true, do_append);                  const char* data_cstr=sdata.cstr();
                   file_write(r.absolute(file_name), 
                           data_cstr, sdata.length(), true, do_append);
                   if(*data_cstr) // not empty (when empty it's not heap memory)
                           pa_free((void*)data_cstr); // not needed anymore
           }
 }  }
   
 static void _count(Request& r, MethodParams&) {  static void _count(Request& r, MethodParams&) {
Line 478  static void _offset(Request& r, MethodPa Line 483  static void _offset(Request& r, MethodPa
                                         "is invalid whence, valid are 'cur' or 'set'");                                          "is invalid whence, valid are 'cur' or 'set'");
                 }                  }
                                   
                 Value& offset_expr=params.as_junction(params.count()-1, "offset must be expression");                  int offset=params.as_int(params.count()-1, "offset must be expression", r);
                 table.offset(absolute, r.process_to_value(offset_expr).as_int());                  table.offset(absolute, offset);
         } else          } else
                 r.write_no_lang(*new VInt(table.current()));                  r.write_no_lang(*new VInt(table.current()));
 }  }
Line 659  static void _hash(Request& r, MethodPara Line 664  static void _hash(Request& r, MethodPara
                                 int saved_current=self_table.current();                                  int saved_current=self_table.current();
                                 self_table.for_each(table_row_to_hash, &info);                                  self_table.for_each(table_row_to_hash, &info);
                                 self_table.set_current(saved_current);                                  self_table.set_current(saved_current);
   
                                   result.extract_default();
                         }                          }
                 }                  }
         r.write_no_lang(result);          r.write_no_lang(result);
Line 840  static void _join(Request& r, MethodPara Line 847  static void _join(Request& r, MethodPara
 #ifndef DOXYGEN  #ifndef DOXYGEN
 class Table_sql_event_handlers: public SQL_Driver_query_event_handlers {  class Table_sql_event_handlers: public SQL_Driver_query_event_handlers {
         ArrayString& columns;          ArrayString& columns;
           int columns_count;
         ArrayString* row;          ArrayString* row;
 public:  public:
         Table* table;          Table* table;
Line 860  public: Line 868  public:
         bool before_rows(SQL_Error& error) {           bool before_rows(SQL_Error& error) { 
                 try {                  try {
                         table=new Table(&columns);                          table=new Table(&columns);
                           columns_count=columns.count();
                         return false;                          return false;
                 } catch(...) {                  } catch(...) {
                         error=SQL_Error("exception occured in Table_sql_event_handlers::before_rows");                          error=SQL_Error("exception occured in Table_sql_event_handlers::before_rows");
Line 868  public: Line 877  public:
         }          }
         bool add_row(SQL_Error& error) {          bool add_row(SQL_Error& error) {
                 try {                  try {
                         *table+=row=new ArrayString;                          *table+=row=new ArrayString(columns_count);
                         return false;                          return false;
                 } catch(...) {                  } catch(...) {
                         error=SQL_Error("exception occured in Table_sql_event_handlers::add_row");                          error=SQL_Error("exception occured in Table_sql_event_handlers::add_row");
Line 938  static void _sql(Request& r, MethodParam Line 947  static void _sql(Request& r, MethodParam
         ulong offset=0;          ulong offset=0;
         if(params.count()>1) {          if(params.count()>1) {
                 Value& voptions=params.as_no_junction(1, "options must be hash, not code");                  Value& voptions=params.as_no_junction(1, "options must be hash, not code");
                 if(!voptions.is_string())                  if(voptions.is_defined() && !voptions.is_string())
                         if(HashStringValue* options=voptions.get_hash()) {                          if(HashStringValue* options=voptions.get_hash()) {
                                 int valid_options=0;                                  int valid_options=0;
                                 if(Value* vbind=options->get(sql_bind_name)) {                                  if(Value* vbind=options->get(sql_bind_name)) {
Line 980  static void _sql(Request& r, MethodParam Line 989  static void _sql(Request& r, MethodParam
 #endif    #endif  
         r.connection()->query(          r.connection()->query(
                 statement_cstr,                   statement_cstr, 
                 0, 0,                  placeholders_count, placeholders,
                 offset, limit,                   offset, limit, 
                 handlers,                  handlers,
                 statement_string);                  statement_string);

Removed from v.1.205  
changed lines
  Added in v.1.220


E-mail: