@onurege3467/zerohelper 8.0.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +292 -612
- package/dist/database/IDatabase.d.ts +77 -0
- package/dist/database/IDatabase.js +10 -0
- package/dist/database/cacheWrapper.d.ts +31 -0
- package/dist/database/cacheWrapper.js +228 -0
- package/dist/database/index.d.ts +11 -0
- package/dist/database/index.js +94 -0
- package/dist/database/json.d.ts +32 -0
- package/dist/database/json.js +210 -0
- package/dist/database/migration.d.ts +21 -0
- package/dist/database/migration.js +97 -0
- package/dist/database/mongodb.d.ts +24 -0
- package/dist/database/mongodb.js +153 -0
- package/dist/database/mysql.d.ts +31 -0
- package/dist/database/mysql.js +385 -0
- package/dist/database/pg.d.ts +30 -0
- package/dist/database/pg.js +300 -0
- package/dist/database/redis.d.ts +23 -0
- package/dist/database/redis.js +157 -0
- package/dist/database/sqlite.d.ts +25 -0
- package/dist/database/sqlite.js +273 -0
- package/dist/database/types.d.ts +76 -0
- package/dist/database/types.js +2 -0
- package/dist/database/zpack.d.ts +59 -0
- package/dist/database/zpack.js +462 -0
- package/dist/functions/index.d.ts +183 -0
- package/dist/functions/index.js +636 -0
- package/dist/functions/temp_isphone.d.ts +1 -0
- package/dist/functions/temp_isphone.js +7 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +45 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +55 -0
- package/dist/test_zpack.d.ts +1 -0
- package/dist/test_zpack.js +64 -0
- package/package.json +23 -6
- package/database/IDatabase.js +0 -92
- package/database/cacheWrapper.js +0 -585
- package/database/index.js +0 -72
- package/database/json.js +0 -281
- package/database/migration.js +0 -227
- package/database/mongodb.js +0 -203
- package/database/mysql.js +0 -526
- package/database/pg.js +0 -527
- package/database/redis.js +0 -342
- package/database/sqlite.js +0 -551
- package/functions/index.js +0 -705
- package/index.js +0 -7
package/database/pg.js
DELETED
|
@@ -1,527 +0,0 @@
|
|
|
1
|
-
const IDatabase = require('./IDatabase'); // Arayüzü import et
|
|
2
|
-
const { Pool } = require('pg');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @implements {IDatabase}
|
|
6
|
-
*/
|
|
7
|
-
class PostgreSQLDatabase extends IDatabase {
|
|
8
|
-
constructor(config) {
|
|
9
|
-
super();
|
|
10
|
-
this.config = config;
|
|
11
|
-
this.pool = null;
|
|
12
|
-
this._queue = [];
|
|
13
|
-
this._connected = false;
|
|
14
|
-
|
|
15
|
-
this._connectionPromise = new Promise(async (resolve, reject) => {
|
|
16
|
-
try {
|
|
17
|
-
// First, connect to create database if not exists
|
|
18
|
-
const tempPool = new Pool({
|
|
19
|
-
host: config.host,
|
|
20
|
-
port: config.port || 5432,
|
|
21
|
-
user: config.user,
|
|
22
|
-
password: config.password,
|
|
23
|
-
database: 'postgres' // Connect to default database first
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
await tempPool.query(`CREATE DATABASE "${config.database}"`);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
// Database might already exist, ignore error
|
|
30
|
-
if (!error.message.includes('already exists')) {
|
|
31
|
-
console.warn('Database creation warning:', error.message);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
await tempPool.end();
|
|
35
|
-
|
|
36
|
-
// Now connect to the actual database
|
|
37
|
-
this.pool = new Pool({
|
|
38
|
-
host: config.host,
|
|
39
|
-
port: config.port || 5432,
|
|
40
|
-
user: config.user,
|
|
41
|
-
password: config.password,
|
|
42
|
-
database: config.database,
|
|
43
|
-
max: config.connectionLimit || 10,
|
|
44
|
-
idleTimeoutMillis: 30000,
|
|
45
|
-
connectionTimeoutMillis: 2000,
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
this._connected = true;
|
|
49
|
-
resolve(this.pool);
|
|
50
|
-
this._processQueue(); // Process any queued requests
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error("PostgreSQL connection error:", error);
|
|
53
|
-
reject(error);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Değerin türüne göre PostgreSQL column türünü otomatik belirler
|
|
60
|
-
*/
|
|
61
|
-
_getColumnType(value) {
|
|
62
|
-
if (value === null || value === undefined) {
|
|
63
|
-
return 'TEXT'; // Null değerler için varsayılan
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (typeof value === 'boolean') {
|
|
67
|
-
return 'BOOLEAN';
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (typeof value === 'number') {
|
|
71
|
-
if (Number.isInteger(value)) {
|
|
72
|
-
// Integer range kontrolü
|
|
73
|
-
if (value >= -32768 && value <= 32767) {
|
|
74
|
-
return 'SMALLINT';
|
|
75
|
-
} else if (value >= -2147483648 && value <= 2147483647) {
|
|
76
|
-
return 'INTEGER';
|
|
77
|
-
} else {
|
|
78
|
-
return 'BIGINT';
|
|
79
|
-
}
|
|
80
|
-
} else {
|
|
81
|
-
// Float/Double için
|
|
82
|
-
return 'DOUBLE PRECISION';
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (typeof value === 'string') {
|
|
87
|
-
const length = value.length;
|
|
88
|
-
if (length <= 255) {
|
|
89
|
-
return 'VARCHAR(255)';
|
|
90
|
-
} else {
|
|
91
|
-
return 'TEXT';
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (typeof value === 'object') {
|
|
96
|
-
// Array ve Object'ler JSONB olarak saklanır
|
|
97
|
-
return 'JSONB';
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (value instanceof Date) {
|
|
101
|
-
return 'TIMESTAMP';
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Varsayılan
|
|
105
|
-
return 'TEXT';
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Birden fazla değere göre en uygun column türünü belirler
|
|
110
|
-
*/
|
|
111
|
-
_getBestColumnType(values) {
|
|
112
|
-
const types = values.map(val => this._getColumnType(val));
|
|
113
|
-
const uniqueTypes = [...new Set(types)];
|
|
114
|
-
|
|
115
|
-
// Eğer hepsi aynı türse, o türü kullan
|
|
116
|
-
if (uniqueTypes.length === 1) {
|
|
117
|
-
return uniqueTypes[0];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Mixed türler için öncelik sırası
|
|
121
|
-
const typePriority = {
|
|
122
|
-
'TEXT': 10,
|
|
123
|
-
'JSONB': 9,
|
|
124
|
-
'VARCHAR(255)': 8,
|
|
125
|
-
'TIMESTAMP': 7,
|
|
126
|
-
'DOUBLE PRECISION': 6,
|
|
127
|
-
'BIGINT': 5,
|
|
128
|
-
'INTEGER': 4,
|
|
129
|
-
'SMALLINT': 3,
|
|
130
|
-
'BOOLEAN': 2
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
// En yüksek öncelikli türü seç
|
|
134
|
-
let bestType = uniqueTypes[0];
|
|
135
|
-
let bestPriority = typePriority[bestType] || 0;
|
|
136
|
-
|
|
137
|
-
for (const type of uniqueTypes) {
|
|
138
|
-
const priority = typePriority[type] || 0;
|
|
139
|
-
if (priority > bestPriority) {
|
|
140
|
-
bestType = type;
|
|
141
|
-
bestPriority = priority;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return bestType;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Eksik kolonları kontrol eder ve ekler
|
|
150
|
-
*/
|
|
151
|
-
async _ensureMissingColumns(table, data) {
|
|
152
|
-
const existingColumns = await this.query(`
|
|
153
|
-
SELECT column_name
|
|
154
|
-
FROM information_schema.columns
|
|
155
|
-
WHERE table_name = $1 AND table_schema = 'public'
|
|
156
|
-
`, [table]);
|
|
157
|
-
|
|
158
|
-
if (!existingColumns || existingColumns.length === 0) {
|
|
159
|
-
throw new Error(`Table ${table} does not exist.`);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const existingColumnNames = existingColumns.map(col => col.column_name);
|
|
163
|
-
|
|
164
|
-
for (const key of Object.keys(data)) {
|
|
165
|
-
if (!existingColumnNames.includes(key)) {
|
|
166
|
-
const columnType = this._getColumnType(data[key]);
|
|
167
|
-
const alterSQL = `ALTER TABLE "${table}" ADD COLUMN "${key}" ${columnType}`;
|
|
168
|
-
await this.query(alterSQL);
|
|
169
|
-
console.log(`Added missing column '${key}' to table '${table}' with type ${columnType}`);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async _queueRequest(operation) {
|
|
175
|
-
if (this._connected) {
|
|
176
|
-
return operation();
|
|
177
|
-
} else {
|
|
178
|
-
return new Promise((resolve, reject) => {
|
|
179
|
-
this._queue.push({ operation, resolve, reject });
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
async _processQueue() {
|
|
185
|
-
if (!this._connected) return;
|
|
186
|
-
|
|
187
|
-
while (this._queue.length > 0) {
|
|
188
|
-
const { operation, resolve, reject } = this._queue.shift();
|
|
189
|
-
try {
|
|
190
|
-
const result = await operation();
|
|
191
|
-
resolve(result);
|
|
192
|
-
} catch (error) {
|
|
193
|
-
reject(error);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async query(sql, params = []) {
|
|
199
|
-
return this._queueRequest(async () => {
|
|
200
|
-
const pool = await this._connectionPromise;
|
|
201
|
-
const result = await pool.query(sql, params);
|
|
202
|
-
return result.rows;
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async ensureTable(table, data = {}) {
|
|
207
|
-
return this._queueRequest(async () => {
|
|
208
|
-
const tables = await this.query(`
|
|
209
|
-
SELECT table_name
|
|
210
|
-
FROM information_schema.tables
|
|
211
|
-
WHERE table_schema = 'public' AND table_name = $1
|
|
212
|
-
`, [table]);
|
|
213
|
-
|
|
214
|
-
if (tables.length === 0) {
|
|
215
|
-
const columnDefinitions = Object.keys(data).map(col => {
|
|
216
|
-
const columnType = this._getColumnType(data[col]);
|
|
217
|
-
return `"${col}" ${columnType}`;
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
let columnsPart = '';
|
|
221
|
-
if (columnDefinitions.length > 0) {
|
|
222
|
-
columnsPart = ', ' + columnDefinitions.join(", ");
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const createTableSQL = `
|
|
226
|
-
CREATE TABLE "${table}" (
|
|
227
|
-
"_id" SERIAL PRIMARY KEY
|
|
228
|
-
${columnsPart}
|
|
229
|
-
)
|
|
230
|
-
`;
|
|
231
|
-
await this.query(createTableSQL);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
async insert(table, data) {
|
|
237
|
-
return this._queueRequest(async () => {
|
|
238
|
-
const copy = { ...data };
|
|
239
|
-
await this.ensureTable(table, copy);
|
|
240
|
-
|
|
241
|
-
// Eksik kolonları ekle
|
|
242
|
-
await this._ensureMissingColumns(table, copy);
|
|
243
|
-
|
|
244
|
-
const existingColumns = await this.query(`
|
|
245
|
-
SELECT column_name, column_default, is_nullable, data_type
|
|
246
|
-
FROM information_schema.columns
|
|
247
|
-
WHERE table_name = $1 AND table_schema = 'public'
|
|
248
|
-
`, [table]);
|
|
249
|
-
|
|
250
|
-
const primaryKeyColumn = existingColumns.find(col =>
|
|
251
|
-
col.column_default && col.column_default.includes('nextval')
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
const insertData = { ...copy };
|
|
255
|
-
// Remove the auto-incrementing primary key from insertData if it's present
|
|
256
|
-
if (primaryKeyColumn && insertData[primaryKeyColumn.column_name] !== undefined) {
|
|
257
|
-
delete insertData[primaryKeyColumn.column_name];
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const keys = Object.keys(insertData);
|
|
261
|
-
const placeholders = keys.map((_, index) => `$${index + 1}`).join(",");
|
|
262
|
-
const values = Object.values(insertData).map(value => this._serializeValue(value));
|
|
263
|
-
const sql = `INSERT INTO "${table}" (${keys.map(k => `"${k}"`).join(",")}) VALUES (${placeholders}) RETURNING "_id"`;
|
|
264
|
-
|
|
265
|
-
const result = await this.query(sql, values);
|
|
266
|
-
return result[0]._id;
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
async update(table, data, where) {
|
|
271
|
-
return this._queueRequest(async () => {
|
|
272
|
-
await this.ensureTable(table, { ...data, ...where });
|
|
273
|
-
|
|
274
|
-
// Eksik kolonları ekle
|
|
275
|
-
await this._ensureMissingColumns(table, { ...data, ...where });
|
|
276
|
-
|
|
277
|
-
const setString = Object.keys(data).map((k, i) => `"${k}" = $${i + 1}`).join(", ");
|
|
278
|
-
const whereString = Object.keys(where).map((k, i) => `"${k}" = $${Object.keys(data).length + i + 1}`).join(" AND ");
|
|
279
|
-
const sql = `UPDATE "${table}" SET ${setString} WHERE ${whereString}`;
|
|
280
|
-
|
|
281
|
-
const result = await this.query(sql, [...Object.values(data).map(v => this._serializeValue(v)), ...Object.values(where).map(v => this._serializeValue(v))]);
|
|
282
|
-
return result.length; // PostgreSQL doesn't return affectedRows in the same way
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
async delete(table, where) {
|
|
287
|
-
return this._queueRequest(async () => {
|
|
288
|
-
if (!where || Object.keys(where).length === 0) return 0;
|
|
289
|
-
await this.ensureTable(table, { ...where });
|
|
290
|
-
|
|
291
|
-
// Eksik kolonları ekle (where koşulları için)
|
|
292
|
-
await this._ensureMissingColumns(table, where);
|
|
293
|
-
|
|
294
|
-
const whereString = Object.keys(where).map((k, i) => `"${k}" = $${i + 1}`).join(" AND ");
|
|
295
|
-
const sql = `DELETE FROM "${table}" WHERE ${whereString}`;
|
|
296
|
-
const result = await this.query(sql, Object.values(where).map(v => this._serializeValue(v)));
|
|
297
|
-
return result.length;
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
async select(table, where = null) {
|
|
302
|
-
return this._queueRequest(async () => {
|
|
303
|
-
await this.ensureTable(table, where || {});
|
|
304
|
-
|
|
305
|
-
// Eğer where koşulu varsa, eksik kolonları ekle
|
|
306
|
-
if (where && Object.keys(where).length > 0) {
|
|
307
|
-
await this._ensureMissingColumns(table, where);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
let sql = `SELECT * FROM "${table}"`;
|
|
311
|
-
let params = [];
|
|
312
|
-
|
|
313
|
-
if (where && Object.keys(where).length > 0) {
|
|
314
|
-
const whereString = Object.keys(where).map((k, i) => `"${k}" = $${i + 1}`).join(" AND ");
|
|
315
|
-
sql += ` WHERE ${whereString}`;
|
|
316
|
-
params = Object.values(where).map(v => this._serializeValue(v));
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const rows = await this.query(sql, params);
|
|
320
|
-
return rows.map(row => {
|
|
321
|
-
const newRow = {};
|
|
322
|
-
for (const key in row) {
|
|
323
|
-
newRow[key] = this._deserializeValue(row[key]);
|
|
324
|
-
}
|
|
325
|
-
return newRow;
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
async set(table, data, where) {
|
|
331
|
-
return this._queueRequest(async () => {
|
|
332
|
-
await this.ensureTable(table, { ...data, ...where });
|
|
333
|
-
|
|
334
|
-
// Eksik kolonları ekle
|
|
335
|
-
await this._ensureMissingColumns(table, { ...data, ...where });
|
|
336
|
-
|
|
337
|
-
const existing = await this.select(table, where);
|
|
338
|
-
if (existing.length === 0) {
|
|
339
|
-
return await this.insert(table, { ...where, ...data });
|
|
340
|
-
} else {
|
|
341
|
-
return await this.update(table, data, where);
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
async selectOne(table, where = null) {
|
|
347
|
-
return this._queueRequest(async () => {
|
|
348
|
-
const results = await this.select(table, where);
|
|
349
|
-
if (results[0]) {
|
|
350
|
-
const newResult = {};
|
|
351
|
-
for (const key in results[0]) {
|
|
352
|
-
newResult[key] = this._deserializeValue(results[0][key]);
|
|
353
|
-
}
|
|
354
|
-
return newResult;
|
|
355
|
-
}
|
|
356
|
-
return null;
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
async deleteOne(table, where) {
|
|
361
|
-
return this._queueRequest(async () => {
|
|
362
|
-
await this.ensureTable(table, where);
|
|
363
|
-
|
|
364
|
-
// Eksik kolonları ekle (where koşulları için)
|
|
365
|
-
await this._ensureMissingColumns(table, where);
|
|
366
|
-
|
|
367
|
-
const row = await this.selectOne(table, where);
|
|
368
|
-
if (!row) return 0;
|
|
369
|
-
|
|
370
|
-
const whereString = Object.keys(where).map((k, i) => `"${k}" = $${i + 1}`).join(" AND ");
|
|
371
|
-
const sql = `DELETE FROM "${table}" WHERE ${whereString} AND ctid = (SELECT ctid FROM "${table}" WHERE ${whereString} LIMIT 1)`;
|
|
372
|
-
const result = await this.query(sql, [...Object.values(where).map(v => this._serializeValue(v)), ...Object.values(where).map(v => this._serializeValue(v))]);
|
|
373
|
-
return result.length;
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
async updateOne(table, data, where) {
|
|
378
|
-
return this._queueRequest(async () => {
|
|
379
|
-
await this.ensureTable(table, { ...data, ...where });
|
|
380
|
-
|
|
381
|
-
// Eksik kolonları ekle
|
|
382
|
-
await this._ensureMissingColumns(table, { ...data, ...where });
|
|
383
|
-
|
|
384
|
-
const setString = Object.keys(data).map((k, i) => `"${k}" = $${i + 1}`).join(", ");
|
|
385
|
-
const whereString = Object.keys(where).map((k, i) => `"${k}" = $${Object.keys(data).length + i + 1}`).join(" AND ");
|
|
386
|
-
const sql = `UPDATE "${table}" SET ${setString} WHERE ${whereString} AND ctid = (SELECT ctid FROM "${table}" WHERE ${whereString} LIMIT 1)`;
|
|
387
|
-
|
|
388
|
-
const result = await this.query(sql, [...Object.values(data).map(v => this._serializeValue(v)), ...Object.values(where).map(v => this._serializeValue(v)), ...Object.values(where).map(v => this._serializeValue(v))]);
|
|
389
|
-
return result.length;
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
async bulkInsert(table, dataArray) {
|
|
394
|
-
return this._queueRequest(async () => {
|
|
395
|
-
if (!Array.isArray(dataArray) || dataArray.length === 0) return 0;
|
|
396
|
-
await this.ensureTable(table, dataArray[0]);
|
|
397
|
-
|
|
398
|
-
const existingColumns = await this.query(`
|
|
399
|
-
SELECT column_name
|
|
400
|
-
FROM information_schema.columns
|
|
401
|
-
WHERE table_name = $1 AND table_schema = 'public'
|
|
402
|
-
`, [table]);
|
|
403
|
-
|
|
404
|
-
const existingColumnNames = existingColumns.map(col => col.column_name);
|
|
405
|
-
|
|
406
|
-
// Tüm datalardan gelen tüm anahtarları topla
|
|
407
|
-
const allKeys = new Set();
|
|
408
|
-
dataArray.forEach(obj => {
|
|
409
|
-
Object.keys(obj).forEach(key => allKeys.add(key));
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
// Eksik kolonları kontrol et ve ekle
|
|
413
|
-
for (const key of allKeys) {
|
|
414
|
-
if (!existingColumnNames.includes(key)) {
|
|
415
|
-
// Tüm değerleri kontrol ederek en uygun türü belirle
|
|
416
|
-
const columnValues = dataArray
|
|
417
|
-
.map(obj => obj[key])
|
|
418
|
-
.filter(val => val !== undefined && val !== null);
|
|
419
|
-
const columnType = columnValues.length > 0 ? this._getBestColumnType(columnValues) : 'TEXT';
|
|
420
|
-
await this.query(`ALTER TABLE "${table}" ADD COLUMN "${key}" ${columnType}`);
|
|
421
|
-
console.log(`Added missing column '${key}' to table '${table}' with type ${columnType}`);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
const keys = Array.from(allKeys);
|
|
426
|
-
|
|
427
|
-
// PostgreSQL için VALUES clause oluştur
|
|
428
|
-
const placeholders = dataArray.map((_, rowIndex) =>
|
|
429
|
-
`(${keys.map((_, colIndex) => `$${rowIndex * keys.length + colIndex + 1}`).join(',')})`
|
|
430
|
-
).join(',');
|
|
431
|
-
|
|
432
|
-
const values = dataArray.flatMap(obj => keys.map(k => this._serializeValue(obj[k])));
|
|
433
|
-
const sql = `INSERT INTO "${table}" (${keys.map(k => `"${k}"`).join(",")}) VALUES ${placeholders}`;
|
|
434
|
-
|
|
435
|
-
const result = await this.query(sql, values);
|
|
436
|
-
return result.length;
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
async close() {
|
|
441
|
-
if (this.pool) await this.pool.end();
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// Helper to serialize values for storage
|
|
445
|
-
_serializeValue(value) {
|
|
446
|
-
if (value instanceof Date) {
|
|
447
|
-
return value.toISOString(); // PostgreSQL TIMESTAMP format
|
|
448
|
-
}
|
|
449
|
-
if (Array.isArray(value) || (typeof value === 'object' && value !== null)) {
|
|
450
|
-
return JSON.stringify(value); // PostgreSQL will handle JSONB conversion
|
|
451
|
-
}
|
|
452
|
-
return value;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// Helper to deserialize values after retrieval
|
|
456
|
-
_deserializeValue(value) {
|
|
457
|
-
// PostgreSQL JSONB columns are automatically parsed by pg driver
|
|
458
|
-
// No need for manual JSON parsing unlike MySQL
|
|
459
|
-
return value;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* WHERE clause oluşturur (PostgreSQL $n syntax için)
|
|
464
|
-
* @param {object} where - WHERE koşulları
|
|
465
|
-
* @param {number} startIndex - Başlangıç parameter indeksi
|
|
466
|
-
* @returns {object} - whereClause string ve values array
|
|
467
|
-
*/
|
|
468
|
-
buildWhereClause(where = {}, startIndex = 0) {
|
|
469
|
-
const conditions = Object.keys(where);
|
|
470
|
-
if (conditions.length === 0) {
|
|
471
|
-
return { whereClause: '', values: [] };
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
const whereClause = ' WHERE ' + conditions.map((key, index) =>
|
|
475
|
-
`${key} = $${startIndex + index + 1}`
|
|
476
|
-
).join(' AND ');
|
|
477
|
-
const values = Object.values(where).map(v => this._serializeValue(v));
|
|
478
|
-
|
|
479
|
-
return { whereClause, values };
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Numerik alanları artırır (increment).
|
|
484
|
-
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
485
|
-
* @param {object} increments - Artırılacak alanlar ve miktarları.
|
|
486
|
-
* @param {object} where - Güncelleme koşulları.
|
|
487
|
-
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
488
|
-
*/
|
|
489
|
-
async increment(table, increments, where = {}) {
|
|
490
|
-
const incrementClauses = Object.keys(increments).map((field, index) =>
|
|
491
|
-
`${field} = ${field} + $${index + 1}`
|
|
492
|
-
).join(', ');
|
|
493
|
-
|
|
494
|
-
const incrementValues = Object.values(increments);
|
|
495
|
-
const { whereClause, values: whereValues } = this.buildWhereClause(where, incrementValues.length);
|
|
496
|
-
|
|
497
|
-
const sql = `UPDATE ${table} SET ${incrementClauses}${whereClause}`;
|
|
498
|
-
const allValues = [...incrementValues, ...whereValues];
|
|
499
|
-
|
|
500
|
-
const result = await this.pool.query(sql, allValues);
|
|
501
|
-
return result.rowCount;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Numerik alanları azaltır (decrement).
|
|
506
|
-
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
507
|
-
* @param {object} decrements - Azaltılacak alanlar ve miktarları.
|
|
508
|
-
* @param {object} where - Güncelleme koşulları.
|
|
509
|
-
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
510
|
-
*/
|
|
511
|
-
async decrement(table, decrements, where = {}) {
|
|
512
|
-
const decrementClauses = Object.keys(decrements).map((field, index) =>
|
|
513
|
-
`${field} = ${field} - $${index + 1}`
|
|
514
|
-
).join(', ');
|
|
515
|
-
|
|
516
|
-
const decrementValues = Object.values(decrements);
|
|
517
|
-
const { whereClause, values: whereValues } = this.buildWhereClause(where, decrementValues.length);
|
|
518
|
-
|
|
519
|
-
const sql = `UPDATE ${table} SET ${decrementClauses}${whereClause}`;
|
|
520
|
-
const allValues = [...decrementValues, ...whereValues];
|
|
521
|
-
|
|
522
|
-
const result = await this.pool.query(sql, allValues);
|
|
523
|
-
return result.rowCount;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
module.exports = PostgreSQLDatabase;
|