Diff for /parser3/src/classes/table.C between versions 1.196 and 1.210

version 1.196, 2004/02/11 15:33:13 version 1.210, 2005/08/09 08:14:48
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)
 */  */
   
Line 21  static const char * const IDENT_TABLE_C= Line 21  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 36  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_LIMIT_NAME "limit"  #define SQL_LIMIT_NAME "limit"
 #define SQL_OFFSET_NAME "offset"  #define SQL_OFFSET_NAME "offset"
 #define SQL_DEFAULT_NAME "default"  #define SQL_DEFAULT_NAME "default"
Line 44  DECLARE_CLASS_VAR(table, new MTable, 0); Line 45  DECLARE_CLASS_VAR(table, new MTable, 0);
   
 // globals  // globals
   
   String sql_bind_name(SQL_BIND_NAME);
 String sql_limit_name(SQL_LIMIT_NAME);  String sql_limit_name(SQL_LIMIT_NAME);
 String sql_offset_name(SQL_OFFSET_NAME);  String sql_offset_name(SQL_OFFSET_NAME);
 String sql_default_name(SQL_DEFAULT_NAME);  String sql_default_name(SQL_DEFAULT_NAME);
Line 251  static void skip_empty_and_comment_lines Line 253  static void skip_empty_and_comment_lines
                 while( char c=*data ) {                  while( char c=*data ) {
                         if( c== '\n' || c == '#' ) {                          if( c== '\n' || c == '#' ) {
                                 /*nowhere=*/getrow(&data); // remove empty&comment lines                                  /*nowhere=*/getrow(&data); // remove empty&comment lines
                                 *data_ref=data;                                  if(!(*data_ref=data))
                                           break;
                                 continue;                                  continue;
                         }                          }
                         break;                          break;
Line 260  static void skip_empty_and_comment_lines Line 263  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;          {}
         }  
         void load( HashStringValue& options ) {          void load( HashStringValue& options ) {
                 if(Value* vseparator=options.get(COLUMN_SEPARATOR_NAME)) {                  if(Value* vseparator=options.get(COLUMN_SEPARATOR_NAME)) {
                         options.remove(COLUMN_SEPARATOR_NAME);                          options.remove(COLUMN_SEPARATOR_NAME);
                         const String& sseparator=vseparator->as_string();                          scolumn=&vseparator->as_string();
                         if(sseparator.length()!=1)                          if(scolumn->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();
                 }                  }
                 if(Value* vencloser=options.get(COLUMN_ENCLOSER_NAME)) {                  if(Value* vencloser=options.get(COLUMN_ENCLOSER_NAME)) {
                         options.remove(COLUMN_ENCLOSER_NAME);                          options.remove(COLUMN_ENCLOSER_NAME);
Line 335  static void _load(Request& r, MethodPara Line 337  static void _load(Request& r, MethodPara
         Table::element_type row(new ArrayString);          Table::element_type row(new ArrayString);
         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.delim && !row->count()) // append last empty column [if without \n]                  if(!*sr.piece && !sr.delim && !row->count()) // append last empty column [if without \n]
                         break;                          break;
                 *row+=new String(sr.piece, 0, true);                  *row+=new String(sr.piece, 0, true);
                 if(sr.delim=='\n') {                  if(sr.delim=='\n') {
Line 368  static void maybe_enclose( String& to, c Line 370  static void maybe_enclose( String& to, c
   
                 to<<*sencloser;                  to<<*sencloser;
         } else          } else
                 to.append(from, String::L_TABLE);                  to<<from;
 }  }
   
   
Line 416  static void _save(Request& r, MethodPara Line 418  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 424  static void _save(Request& r, MethodPara Line 426  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 439  static void _save(Request& r, MethodPara Line 441  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);
         }          }
Line 629  static void _hash(Request& r, MethodPara Line 631  static void _hash(Request& r, MethodPara
                                 } else                                  } else
                                         throw Exception("parser.runtime",                                          throw Exception("parser.runtime",
                                                 0,                                                  0,
                                                 "value field(s) must be string or self_table"                                                  "value field(s) must be string or table"
                                         );                                          );
                         } else { // by all columns, including key                          } else { // by all columns, including key
                                 if(!(distinct!=D_ILLEGAL && distinct!=D_FIRST))                                  if(!(distinct!=D_ILLEGAL && distinct!=D_FIRST))
Line 644  static void _hash(Request& r, MethodPara Line 646  static void _hash(Request& r, MethodPara
                                         &r,                                          &r,
                                         &self_table,                                          &self_table,
                                         /*key_code=*/key_param->get_junction()?key_param:0,                                          /*key_code=*/key_param->get_junction()?key_param:0,
                                         /*key_field=*/0,                                          /*key_field=*/0/*filled below*/,
                                         &value_fields,                                          &value_fields,
                                         &result.hash(),                                          &result.hash(),
                                         distinct,                                          distinct,
Line 656  static void _hash(Request& r, MethodPara Line 658  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 886  public: Line 890  public:
         }          }
 };  };
 #endif  #endif
   
   static void marshal_bind(
                                                    HashStringValue::key_type aname, 
                                                    HashStringValue::value_type avalue,
                                                    SQL_Driver::Placeholder** pptr) 
   {
           SQL_Driver::Placeholder& ph=**pptr;
           ph.name=aname.cstr();
           ph.value=avalue->as_string().cstr(String::L_UNSPECIFIED);
           ph.is_null=avalue->get_class()==void_class;
           ph.were_updated=false;
   
           (*pptr)++;
   }
   
   // not static, used elsewhere
   int marshal_binds(HashStringValue& hash, SQL_Driver::Placeholder*& placeholders) {
           int hash_count=hash.count();
           placeholders=new(UseGC) SQL_Driver::Placeholder[hash_count];
           SQL_Driver::Placeholder* ptr=placeholders;
           hash.for_each(marshal_bind, &ptr);
           return hash_count;
   }
   
   // not static, used elsewhere
   void unmarshal_bind_updates(HashStringValue& hash, int placeholder_count, SQL_Driver::Placeholder* placeholders) {
           SQL_Driver::Placeholder* ph=placeholders;
           for(int i=0; i<placeholder_count; i++, ph++)
                   if(ph->were_updated) {
                           Value* value;
                           if(ph->is_null)
                                   value=new VVoid();
                           else
                                   if(ph->value)
                                           value=new VString(*new String(ph->value, 0, true/*tainted*/));
                                   else
                                           value=new VString(*new String());                                       
                           hash.put(ph->name, value);
                   }
   }
   
 static void _sql(Request& r, MethodParams& params) {  static void _sql(Request& r, MethodParams& params) {
         Value& statement=params.as_junction(0, "statement must be code");          Value& statement=params.as_junction(0, "statement must be code");
   
           HashStringValue* bind=0;
         ulong limit=0;          ulong limit=0;
         ulong offset=0;          ulong offset=0;
         if(params.count()>1) {          if(params.count()>1) {
Line 896  static void _sql(Request& r, MethodParam Line 942  static void _sql(Request& r, MethodParam
                 if(!voptions.is_string())                  if(!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)) {
                                           valid_options++;
                                           bind=vbind->get_hash();
                                   }
                                 if(Value* vlimit=options->get(sql_limit_name)) {                                  if(Value* vlimit=options->get(sql_limit_name)) {
                                         valid_options++;                                          valid_options++;
                                         limit=(ulong)r.process_to_value(*vlimit).as_double();                                          limit=(ulong)r.process_to_value(*vlimit).as_double();
Line 914  static void _sql(Request& r, MethodParam Line 964  static void _sql(Request& r, MethodParam
                                         "options must be hash");                                          "options must be hash");
         }          }
   
           SQL_Driver::Placeholder* placeholders=0;
           uint placeholders_count=0;
           if(bind)
                   placeholders_count=marshal_binds(*bind, placeholders);
   
         Temp_lang temp_lang(r, String::L_SQL);          Temp_lang temp_lang(r, String::L_SQL);
         const String&  statement_string=r.process_to_string(statement);          const String&  statement_string=r.process_to_string(statement);
         const char* statement_cstr=          const char* statement_cstr=
Line 925  static void _sql(Request& r, MethodParam Line 980  static void _sql(Request& r, MethodParam
         gettimeofday(&mt[0],NULL);          gettimeofday(&mt[0],NULL);
 #endif    #endif  
         r.connection()->query(          r.connection()->query(
                 statement_cstr, offset, limit,                   statement_cstr, 
                   placeholders_count, placeholders,
                   offset, limit, 
                 handlers,                  handlers,
                 statement_string);                  statement_string);
                   
Line 940  static void _sql(Request& r, MethodParam Line 997  static void _sql(Request& r, MethodParam
         r.sql_request_time+=t[1]-t[0];          r.sql_request_time+=t[1]-t[0];
 #endif                            #endif                          
   
           if(bind)
                   unmarshal_bind_updates(*bind, placeholders_count, placeholders);
   
         Table& result=          Table& result=
                 handlers.table?*handlers.table: // query resulted in table? return it                  handlers.table?*handlers.table: // query resulted in table? return it
                 *new Table(Table::columns_type(0)); // query returned no table, fake it                  *new Table(Table::columns_type(0)); // query returned no table, fake it

Removed from v.1.196  
changed lines
  Added in v.1.210


E-mail: