Changeset 46

Show
Ignore:
Timestamp:
01/10/07 11:33:54 (2 years ago)
Author:
cryogen
Message:

- Add type information to pgresult
- Fix escape in Statement to now be able to use database specific escape

functions, and if in case it cant, to not, to not use a flawed method of
escaping

- Fix bind to replace variables properly and not break when you pass in a

parameter with a '?' in it. - This is only partially done and needs to
respect types properly.

- Other DBDs will need to have escape functions added to them, whether generic

or db specific.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dbi/Database.d

    r45 r46  
    7272        return new Statement(cast(Database)this, sql); 
    7373    } 
     74 
     75  /* Escape a string using the database's native method if possible 
     76   * 
     77   * Params: 
     78   *  str = The string to escape 
     79   * 
     80   * Returns: 
     81   *  The escaped string. 
     82   */ 
     83 
     84  char[] escape (char[] str) 
     85  { 
     86    char[] result; 
     87    int count = 0; 
     88 
     89    // Maximum length needed if every char is to be quoted 
     90    result.length = str.length * 2; 
     91    for(int i = 0; i < str.length; i++) 
     92    { 
     93      switch(str[i]) 
     94      { 
     95        case '"': 
     96        case '\'': 
     97        case '\\': 
     98          result[count++] = '\\'; 
     99          break; 
     100        default: 
     101          break; 
     102      } 
     103      result[count++] = str[i]; 
     104    } 
     105 
     106    result.length = count; 
     107 
     108    return result; 
     109  } 
    74110 
    75111    /** 
  • trunk/dbi/Statement.d

    r45 r46  
    9898     *  The escaped form of string. 
    9999     */ 
    100     char[] escape (char[] string) { 
    101         version (Ares) { 
    102             return std.regexp.sub(string, "'", "''"); 
    103         } else { 
    104             return std.string.replace(string, "'", "''"); 
    105         } 
     100    char[] escape (char[] string)  
     101  { 
     102    if(database !is null) 
     103      return database.escape(string); 
     104    else 
     105    { 
     106      char[] result; 
     107      int count = 0; 
     108 
     109      // Maximum length needed if every char is to be quoted 
     110      result.length = string.length * 2; 
     111      for(int i = 0; i < string.length; i++) 
     112      { 
     113        switch(string[i]) 
     114        { 
     115          case '"': 
     116          case '\'': 
     117          case '\\': 
     118            result[count++] = '\\'; 
     119            break; 
     120          default: 
     121            break; 
     122        } 
     123        result[count++] = string[i]; 
     124      } 
     125 
     126      result.length = count; 
     127      return result; 
     128    }  
    106129    } 
    107130 
     
    115138     *  Raise an exception if binds.length != count(sql, "?") 
    116139     */ 
    117     char[] getSqlByQM () { 
    118         char[] result = sql; 
    119         int qmIdx = 0, qmCount = 0; 
    120  
    121         void replace () { 
    122             result = result[0 .. qmIdx] ~ "'" ~ binds[qmCount] ~ "'" ~ result[qmIdx + 1 .. result.length]; 
    123                 qmCount++; 
    124         } 
    125  
    126         version (Ares) { 
    127             while((qmIdx = std.regexp.find(result, "\\u003F")) != size_t.max) { 
    128                 replace(); 
    129             } 
    130         } else { 
    131             while ((qmIdx = std.string.find(result, "?")) != -1) { 
    132                 replace(); 
    133             } 
    134         } 
     140    char[] getSqlByQM ()  
     141  { 
     142        char[] result;  
     143    int i = 0, j = 0, count = 0; 
     144 
     145    // binds.length is for the '', only 1 because we replace the ? too 
     146    result.length = sql.length + binds.length;      
     147    for(i = 0; i < binds.length; i++) 
     148      result.length = result.length + binds[i].length; 
     149 
     150    for(i = 0; i < sql.length; i++) 
     151    { 
     152      if(sql[i] == '?') 
     153      { 
     154        result[j++] = '\''; 
     155        result[j..j + binds[count].length] = binds[count]; 
     156        j += binds[count++].length; 
     157        result[j++] = '\''; 
     158      } 
     159      else 
     160        result[j++] = sql[i]; 
     161    } 
     162 
     163    sql = result; 
    135164        return result; 
    136165    } 
     
    226255    s1("dbi.Statement:"); 
    227256    Statement stmt = new Statement(null, "SELECT * FROM people"); 
    228     char[] resultingSql = "SELECT * FROM people WHERE id = '10' OR name LIKE 'John Mc''Donald'"; 
     257    char[] resultingSql = "SELECT * FROM people WHERE id = '10' OR name LIKE 'John Mc\\'Donald'"; 
    229258 
    230259    s2("escape"); 
    231     assert(stmt.escape("John Mc'Donald") == "John Mc''Donald"); 
     260    assert(stmt.escape("John Mc'Donald") == "John Mc\\'Donald"); 
    232261 
    233262    s2("simple sql"); 
     
    239268    stmt.bind(1, "10"); 
    240269    stmt.bind(2, "John Mc'Donald"); 
     270 
    241271    assert(stmt.getSql() == resultingSql); 
    242272 
     
    251281    stmt.bind("id", "10"); 
    252282    stmt.bind("name", "John Mc'Donald"); 
    253     assert(stmt.getBoundValue("name") == "John Mc''Donald"); 
     283    assert(stmt.getBoundValue("name") == "John Mc\\'Donald"); 
    254284    assert(stmt.getSql() == resultingSql); 
    255285} 
  • trunk/dbi/pg/PgDatabase.d

    r45 r46  
    121121        } 
    122122    } 
     123 
     124  /* Escape a string using the database's native method if possible 
     125   * 
     126   * Params: 
     127   *  str = The string to escape 
     128   * 
     129   * Returns: 
     130   *  The escaped string. 
     131   */ 
     132 
     133  override char[] escape (char[] str) 
     134  { 
     135    char[] result; 
     136 
     137    if(str == "") 
     138      return str; 
     139 
     140    result.length = str.length * 2; 
     141 
     142    // It's ok to send str.ptr here because string doesnt need to be 0-term 
     143    int len = PQescapeStringConn(connection, result.ptr, str.ptr, str.length,  
     144        null); 
     145    result.length = len; 
     146 
     147    return result; 
     148  } 
    123149 
    124150    /** 
  • trunk/dbi/pg/PgResult.d

    r45 r46  
    4949        Row r = new Row(); 
    5050        for (int a = 0; a < numFields; a++) { 
    51             r.addField(strip(asString(PQfname(results, a))), strip(asString(PQgetvalue(results, index, a))), "", 0); 
     51            r.addField(strip(asString(PQfname(results, a))),  
     52          strip(asString(PQgetvalue(results, index, a))), "",  
     53          PQftype(results, a)); 
    5254        } 
    5355        index++;