Build fix. We need to escape the path or http.request would fail.
[WebKit.git] / Websites / perf.webkit.org / tools / js / database.js
1 "use strict";
2
3 const pg = require('pg');
4 const config = require('./config.js');
5
6 class Database {
7     constructor(databaseName)
8     {
9         this._client = null;
10         this._databaseName = databaseName || config.value('database.name');
11     }
12
13     connect(options)
14     {
15         console.assert(this._client === null);
16
17         let username = config.value('database.username');
18         let password = config.value('database.password');
19         let host = config.value('database.host');
20         let port = config.value('database.port');
21
22         // No need to worry about escaping strings since they are only set by someone who can write to config.json.
23         let connectionString = `tcp://${username}:${password}@${host}:${port}/${this._databaseName}`;
24
25         let client = new pg.Client(connectionString);
26         if (!options || !options.keepAlive)
27             client.on('drain', this.disconnect.bind(this));
28
29         this._client = client;
30
31         return new Promise(function (resolve, reject) {
32             client.connect(function (error) {
33                 if (error)
34                     reject(error);
35                 resolve();
36             });
37         });
38     }
39
40     disconnect()
41     {
42         if (this._client) {
43             this._client.end();
44             this._client = null;
45         }
46     }
47
48     query(statement, parameters)
49     {
50         console.assert(this._client);
51         var client = this._client;
52         return new Promise(function (resolve, reject) {
53             client.query(statement, parameters || [], function (error, result) {
54                 if (error)
55                     reject(error);
56                 else
57                     resolve(result);
58             });
59         });
60     }
61
62     selectAll(table, columnToSortBy)
63     {
64         return this.selectRows(table, {}, {sortBy: columnToSortBy});
65     }
66
67     selectFirstRow(table, params, columnToSortBy)
68     {
69         return this.selectRows(table, params, {sortBy: columnToSortBy, limit: 1}).then(function (rows) {
70             return rows[0];
71         });
72     }
73
74     selectRows(table, params, options)
75     {
76         let prefix = '';
77         if (table in tableToPrefixMap)
78             prefix = tableToPrefixMap[table] + '_';
79
80         options = options || {};
81
82         let columnNames = [];
83         let placeholders = [];
84         let values = [];
85         for (let name in params) {
86             columnNames.push(prefix + name);
87             placeholders.push('$' + columnNames.length);
88             values.push(params[name]);
89         }
90
91         let qualifier = '';
92         if (columnNames.length)
93             qualifier += ` WHERE (${columnNames.join(',')}) = (${placeholders.join(',')})`;
94         qualifier += ` ORDER BY ${prefix}${options.sortBy || 'id'}`;
95         if (options && options.limit)
96             qualifier += ` LIMIT ${options.limit}`;
97
98         return this.query(`SELECT * FROM ${table}${qualifier}`, values).then(function (result) {
99             return result.rows.map(function (row) {
100                 let formattedResult = {};
101                 for (let columnName in row) {
102                     let formattedName = columnName;
103                     if (formattedName.startsWith(prefix))
104                         formattedName = formattedName.substring(prefix.length);
105                     formattedResult[formattedName] = row[columnName];
106                 }
107                 return formattedResult;
108             });
109         });
110     }
111
112     insert(table, parameters)
113     {
114         let columnNames = [];
115         let placeholders = [];
116         let values = [];
117         for (let name in parameters) {
118             values.push(parameters[name]);
119             if (table in tableToPrefixMap)
120                 name = tableToPrefixMap[table] + '_' + name;
121             columnNames.push(name);
122             placeholders.push(`\$${placeholders.length + 1}`);
123         }
124         return this.query(`INSERT INTO ${table} (${columnNames}) VALUES (${placeholders})`, values);
125     }
126 }
127
128 const tableToPrefixMap = {
129     'aggregators': 'aggregator',
130     'analysis_tasks': 'task',
131     'analysis_test_groups': 'testgroup',
132     'bug_trackers': 'tracker',
133     'build_triggerables': 'triggerable',
134     'build_requests': 'request',
135     'build_slaves': 'slave',
136     'builds': 'build',
137     'builders': 'builder',
138     'commits': 'commit',
139     'committers': 'committer',
140     'test_configurations': 'config',
141     'test_metrics': 'metric',
142     'test_runs': 'run',
143     'tests': 'test',
144     'tracker_repositories': 'tracrepo',
145     'platforms': 'platform',
146     'reports': 'report',
147     'repositories': 'repository',
148     'root_sets': 'rootset',
149     'roots': 'root',
150     'run_iterations': 'iteration',
151 }
152
153 if (typeof module != 'undefined')
154     module.exports = Database;