This file is indexed.

/usr/include/dballe/sql/mysql.h is in libdballe-dev 7.21-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/** @file
 * MySQL DB connector
 */
#ifndef DBALLE_SQL_MYSQL_H
#define DBALLE_SQL_MYSQL_H

#include <dballe/sql/sql.h>
#include <mysql.h>
#include <cstdlib>
#include <vector>

namespace dballe {
namespace sql {
struct MySQLStatement;

/**
 * Report a MySQL error
 */
struct error_mysql : public error_db
{
    std::string msg;

    error_mysql(MYSQL* db, const std::string& msg);
    error_mysql(const std::string& dbmsg, const std::string& msg);
    ~error_mysql() throw () {}

    const char* what() const noexcept override { return msg.c_str(); }

    static void throwf(MYSQL* db, const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3);
};

namespace mysql {

struct ConnectInfo
{
    std::string host;
    std::string user;
    bool has_passwd = false;
    std::string passwd;
    bool has_dbname = false;
    std::string dbname;
    unsigned port = 0;
    std::string unix_socket;

    // Reset everything to defaults
    void reset();
    void parse_url(const std::string& url);
    // Modeled after http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
    std::string to_url() const;
};

struct Row
{
    MYSQL_RES* res = nullptr;
    MYSQL_ROW row = nullptr;

    Row(MYSQL_RES* res, MYSQL_ROW row) : res(res), row(row) {}

    operator bool() const { return row != nullptr; }
    operator MYSQL_ROW() { return row; }
    operator const MYSQL_ROW() const { return row; }

    int as_int(unsigned col) const { return strtol(row[col], 0, 10); }
    unsigned as_unsigned(unsigned col) const { return strtoul(row[col], 0, 10); }
    const char* as_cstring(unsigned col) const { return row[col]; }
    std::string as_string(unsigned col) const { return std::string(row[col], mysql_fetch_lengths(res)[col]); }
    std::vector<uint8_t> as_blob(unsigned col) const
    {
        return std::vector<uint8_t>(row[col], row[col] + mysql_fetch_lengths(res)[col]);
    }
    Datetime as_datetime(int col) const;
    bool isnull(unsigned col) const { return row[col] == nullptr; }
};

struct Result
{
    MYSQL_RES* res = nullptr;

    Result() : res(nullptr) {}
    Result(MYSQL_RES* res) : res(res) {}
    ~Result() { if (res) mysql_free_result(res); }

    /// Implement move
    Result(Result&& o) : res(o.res) { o.res = nullptr; }
    Result& operator=(Result&& o)
    {
        if (this == &o) return *this;
        if (res) mysql_free_result(res);
        res = o.res;
        o.res = nullptr;
        return *this;
    }

    operator bool() const { return res != nullptr; }

    operator MYSQL_RES*() { return res; }
    operator const MYSQL_RES*() const { return res; }

    unsigned rowcount() const { return mysql_num_rows(res); }
    unsigned colcount() const { return mysql_num_fields(res); }

    /// Check that the function returned only one row, and return that row.
    Row expect_one_result();

    /**
     * Fetch one row.
     *
     * Note: mysql_fetch_row does not reset the error indicator, so there is no
     * way to tell the end of the iteration from an error. As a consequence,
     * this is only safe to call after a mysql_store_result.
     *
     * Accessing mysql_use_result results is implemented using execute_fetch.
     */
    Row fetch() { return Row(res, mysql_fetch_row(res)); }

    // Prevent copy
    Result(const Result&) = delete;
    Result& operator=(const Result&) = delete;
};

}


/// Database connection
class MySQLConnection : public Connection
{
protected:
    /// Database connection
    MYSQL* db = nullptr;

    void send_result(mysql::Result&& res, std::function<void(const mysql::Row&)> dest);

protected:
    void init_after_connect();

    // See https://dev.mysql.com/doc/refman/5.0/en/mysql-real-connect.html
    void open(const mysql::ConnectInfo& info);

public:
    MySQLConnection();
    MySQLConnection(const MySQLConnection&) = delete;
    MySQLConnection(const MySQLConnection&&) = delete;
    ~MySQLConnection();
    MySQLConnection& operator=(const MySQLConnection&) = delete;
    MySQLConnection& operator=(const MySQLConnection&&) = delete;

    operator MYSQL*() { return db; }

    // See http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
    void open_url(const std::string& url);
    void open_test();

    /// Escape a C string
    std::string escape(const char* str);
    /// Escape a string
    std::string escape(const std::string& str);
    /// Escape a byte buffer
    std::string escape(const std::vector<uint8_t>& str);

    /**
     * Run a query throwing no exceptions, warning on stderr if it is not
     * successful or if it gives a nonempty result
     */
    void exec_no_data_nothrow(const char* query) noexcept;
    // Run a query, checking that it is successful and it gives no results
    void exec_no_data(const char* query);
    // Run a query, checking that it is successful and it gives no results
    void exec_no_data(const std::string& query);
    // Run a query, with a locally stored result
    mysql::Result exec_store(const char* query);
    // Run a query, with a locally stored result
    mysql::Result exec_store(const std::string& query);
    // Run a query, with a remotely fetched result
    void exec_use(const char* query, std::function<void(const mysql::Row&)> dest);
    // Run a query, with a remotely fetched result
    void exec_use(const std::string& query, std::function<void(const mysql::Row&)> dest);

    std::unique_ptr<Transaction> transaction() override;
    bool has_table(const std::string& name) override;
    std::string get_setting(const std::string& key) override;
    void set_setting(const std::string& key, const std::string& value) override;
    void drop_settings() override;
    void execute(const std::string& query) override;
    void explain(const std::string& query, FILE* out) override;

    /**
     * Delete a table in the database if it exists, otherwise do nothing.
     */
    void drop_table_if_exists(const char* name);

    /**
     * Return LAST_INSERT_ID or LAST_INSER_ROWID or whatever is appropriate for
     * the current database, if supported.
     *
     * If not supported, an exception is thrown.
     */
    int get_last_insert_id();
};

}
}
#endif