Diff for /parser3/src/classes/table.C between versions 1.200 and 1.208.6.2

version 1.200, 2004/03/30 08:41:13 version 1.208.6.2, 2005/08/26 11:08:31
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 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 261  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 336  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.piece && !sr.delim && !row->count()) // append last empty column [if without \n]
                           break;
                 *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;
Line 367  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 415  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 423  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 438  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 474  static void _offset(Request& r, MethodPa Line 477  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 655  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 885  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 895  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 913  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 924  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 939  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.200  
changed lines
  Added in v.1.208.6.2


E-mail: