Skip to content
Snippets Groups Projects
Select Git revision
  • 954c6da53067cbebbb6fe71c7871f183cc2582d6
  • master default protected
  • 9.0
  • 8.0
  • 7.8
  • 7.6
  • 7.4
  • 7.2
  • 7.0
  • 0.6
  • rosuav/latex-markdown-renderer
  • rxnpatch/rxnpatch
  • marcus/gobject-introspection
  • rxnpatch/8.0
  • rosuav/pre-listening-ports
  • nt-tools
  • rosuav/async-annotations
  • rosuav/pgsql-ssl
  • rxnpatch/rxnpatch-broken/2023-10-06T094250
  • grubba/fdlib
  • grubba/wip/sakura/8.0
  • v8.0.2000
  • v8.0.1998
  • v8.0.1996
  • v8.0.1994
  • v8.0.1992
  • v8.0.1990
  • v8.0.1988
  • v8.0.1986
  • rxnpatch/clusters/8.0/2025-04-29T124414
  • rxnpatch/2025-04-29T124414
  • v8.0.1984
  • v8.0.1982
  • v8.0.1980
  • v8.0.1978
  • v8.0.1976
  • v8.0.1974
  • v8.0.1972
  • v8.0.1970
  • v8.0.1968
  • v8.0.1966
41 results

mysql.c

Blame
  • sql_util.pmod 5.83 KiB
    /*
     * $Id: sql_util.pmod,v 1.23 2008/06/30 12:09:15 srb Exp $
     *
     * Some SQL utility functions.
     * They are kept here to avoid circular references.
     *
     * Henrik Grubbström 1999-07-01
     */
    
    #pike __REAL_VERSION__
    
    //! Some SQL utility functions
    
    //! Quote a string so that it can safely be put in a query.
    //!
    //! @param s
    //!   String to quote.
    string quote(string s)
    {
      return replace(s, "\'", "\'\'");
    }
    
    //! Throw an error in case an unimplemented function is called.
    void fallback()
    {
      error( "Function not supported in this database." );
    }
    
    //! Build a raw SQL query, given the cooked query and the variable bindings
    //! It's meant to be used as an emulation engine for those drivers not
    //! providing such a behaviour directly (i.e. Oracle).
    //! The raw query can contain some variables (identified by prefixing
    //! a colon to a name or a number (i.e. ":var" or  ":2"). They will be
    //! replaced by the corresponding value in the mapping.
    //!
    //! @param query
    //!   The query.
    //!
    //! @param bindings
    //!   Optional mapping containing the variable bindings. Make sure that
    //!   no confusion is possible in the query. If necessary, change the
    //!   variables' names.
    string emulate_bindings(string query, mapping(string|int:mixed)|void bindings,
                            void|object driver)
    {
      array(string)k, v;
      if (!bindings)
        return query;
      function my_quote=(driver&&driver->quote?driver->quote:quote);
      v=map(values(bindings),
    	lambda(mixed m) {
    	  if(zero_type(m))
    	    return "NULL";
    	  if(multisetp(m)) m = indices(m)[0];
    	  return "'"+(intp(m)?(string)m:my_quote((string)m))+"'";
    	});
      // Throws if mapping key is empty string.
      k=map(indices(bindings),lambda(string s){
    			    return ( (stringp(s)&&s[0]==':') ?
    				     s : ":"+s);
    			  });
      return replace(query,k,v);
    }
    
    //! Result object wrapper performing utf8 decoding of all fields.
    class UnicodeWrapper (
    		      // The wrapped result object.
    		      protected object master_result
    		      )
    {
      //! Returns the number of rows in the result.
      int num_rows()
      {
        return master_result->num_rows();
      }
    
      //! Returns the number of fields in the result.
      int num_fields()
      {
        return master_result->num_fields();
      }
    
      //! Returns @expr{1@} if there are no more rows in the result.
      int(0..1) eof()
      {
        return master_result->eof();
      }
    
      //! Cached @[fetch_fields()] result.
      protected array(int|mapping(string:mixed)) field_info;
    
      //! Returns Information about the fields in the result.
      //!
      //! The following fields are converted from UTF8 if present:
      //! @mapping
      //!   @member string "name"
      //!     The name of the field. Always present.
      //!   @member string "table"
      //!     The table the field is from. Not present from all databases.
      //!   @member string "default"
      //!     The default value for the column. Not available from all databases.
      //! @endmapping
      array(int|mapping(string:mixed)) fetch_fields()
      {
        if (!field_info) {
          field_info = master_result->fetch_fields();
          foreach(field_info, int|mapping(string:mixed) field) {
    	if (mappingp(field)) {
    	  field->name = utf8_to_string(field->name);
    	  if (field->table) {
    	    field->table = utf8_to_string(field->table);
    	  }
    	  if (field->default) {
    	    field->default = utf8_to_string(field->default);
    	  }
    	}
          }
        }
        return field_info;
      }
    
      //! Skip ahead the specified number of rows.
      void seek(int rows)
      {
        master_result->seek(rows);
      }
    
      //! Fetch the next row from the result.
      //!
      //! All strings in the result are decoded from UTF8.
      int|array(string) fetch_row()
      {
        int|array(string) row = master_result->fetch_row();
        if (!arrayp(row)) return row;
        array(int|mapping(string:mixed)) field_info = fetch_fields();
        foreach(row; int i; string|int val) {
          if (stringp(val)) {
    	row[i] = utf8_to_string(val);
          }
        }
        return row;
      }
    }
    
    #if constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
    
    class MySQLUnicodeWrapper
    //! Result wrapper for MySQL that performs UTF-8 decoding of all
    //! nonbinary fields. Useful if the result charset of the connection
    //! has been set to UTF-8.
    //!
    //! @note
    //! There's normally no need to use this class directly. It's used
    //! automatically when @[Mysql.set_unicode_decode_mode] is activated.
    {
      inherit UnicodeWrapper;
    
      int|array(string) fetch_row()
      {
        int|array(string) row = master_result->fetch_row();
        if (!arrayp(row)) return row;
        array(int|mapping(string:mixed)) field_info = fetch_fields();
        foreach(row; int i; string|int val) {
          if (stringp(val) && field_info[i]->charsetnr != 63) {
    	row[i] = utf8_to_string(val);
          }
        }
        return row;
      }
    }
    
    #else
    
    class MySQLBrokenUnicodeWrapper
    // This one is used to get a buggy unicode support when compiled with
    // an old MySQL client lib that doesn't have the charsetnr property in
    // the field info. It looks at the binary flag instead, which is set
    // for binary fields but might also be set for text fields (e.g. with
    // a definition like "VARCHAR(255) BINARY").
    //
    // I.e. the effect of using this one is that text fields with the
    // binary flag won't be correctly decoded in unicode decode mode.
    //
    // This has to be enabled either by passing "broken-unicode" as
    // charset to Sql.mysql.create or Sql.mysql.set_charset, by calling
    // Sql.mysql.set_unicode_decode_mode(-1), or by defining the
    // environment variable PIKE_BROKEN_MYSQL_UNICODE_MODE. That will
    // cause this buggy variant to be used if and only if the MySQL client
    // lib doesn't support the charsetnr property.
    {
      inherit UnicodeWrapper;
    
      int|array(string) fetch_row()
      {
        int|array(string) row = master_result->fetch_row();
        if (!arrayp(row)) return row;
        array(int|mapping(string:mixed)) field_info = fetch_fields();
        foreach(row; int i; string|int val) {
          if (stringp(val) && field_info[i]->flags &&
    	  !field_info[i]->flags->binary) {
    	row[i] = utf8_to_string(val);
          }
        }
        return row;
      }
    }
    
    #endif