@onurege3467/zerohelper 7.1.0 → 8.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 +762 -0
- package/database/IDatabase.js +18 -0
- package/database/cacheWrapper.js +526 -62
- package/database/index.js +9 -2
- package/database/json.js +59 -0
- package/database/migration.js +227 -0
- package/database/mongodb.js +45 -0
- package/database/mysql.js +61 -0
- package/database/pg.js +64 -0
- package/database/redis.js +342 -0
- package/database/sqlite.js +69 -0
- package/functions/index.js +267 -0
- package/package.json +11 -7
- package/.snapshots/config.json +0 -151
- package/.snapshots/readme.md +0 -11
- package/.snapshots/sponsors.md +0 -44
- package/1.json +0 -15
- package/readme.md +0 -418
- package/test.js +0 -261
- package/test_mysqlonly.js +0 -144
package/database/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
// database-factory.js
|
|
1
2
|
const IDatabase = require('./IDatabase');
|
|
2
3
|
const MySQLDatabase = require('./mysql');
|
|
3
4
|
const SQLiteDatabase = require('./sqlite');
|
|
4
5
|
const MongoDBDatabase = require('./mongodb');
|
|
5
6
|
const JsonDatabase = require('./json');
|
|
6
7
|
const PostgreSQLDatabase = require('./pg');
|
|
8
|
+
const RedisDatabase = require('./redis'); // Yeni Redis adapter
|
|
7
9
|
const CacheWrapper = require('./cacheWrapper');
|
|
10
|
+
const MigrationManager = require('./migration');
|
|
8
11
|
|
|
9
12
|
const adapters = {
|
|
10
13
|
mysql: MySQLDatabase,
|
|
@@ -12,6 +15,7 @@ const adapters = {
|
|
|
12
15
|
mongodb: MongoDBDatabase,
|
|
13
16
|
postgres: PostgreSQLDatabase,
|
|
14
17
|
json: JsonDatabase,
|
|
18
|
+
redis: RedisDatabase, // Redis adapter eklendi
|
|
15
19
|
};
|
|
16
20
|
|
|
17
21
|
/**
|
|
@@ -19,7 +23,7 @@ const adapters = {
|
|
|
19
23
|
* Bu bir "Fabrika Fonksiyonu"dur.
|
|
20
24
|
*
|
|
21
25
|
* @param {object} options - Yapılandırma seçenekleri.
|
|
22
|
-
* @param {keyof adapters} options.adapter - Kullanılacak adaptör ('mysql', 'sqlite', vb.).
|
|
26
|
+
* @param {keyof adapters} options.adapter - Kullanılacak adaptör ('mysql', 'sqlite', 'redis', vb.).
|
|
23
27
|
* @param {object} options.config - Seçilen adaptöre özel yapılandırma.
|
|
24
28
|
* @returns {IDatabase} - IDatabase arayüzünü uygulayan bir örnek döndürür.
|
|
25
29
|
*/
|
|
@@ -61,5 +65,8 @@ function createDatabase(options) {
|
|
|
61
65
|
// Artık varsayılan olarak bu fonksiyonu export ediyoruz.
|
|
62
66
|
module.exports = createDatabase;
|
|
63
67
|
|
|
68
|
+
// Migration manager'ı da export ediyoruz
|
|
69
|
+
module.exports.MigrationManager = MigrationManager;
|
|
70
|
+
|
|
64
71
|
// Eğer hem fonksiyonu hem de tipleri export etmek isterseniz:
|
|
65
|
-
// module.exports = { createDatabase };
|
|
72
|
+
// module.exports = { createDatabase, MigrationManager };
|
package/database/json.js
CHANGED
|
@@ -106,6 +106,11 @@ class JsonDatabase extends IDatabase{
|
|
|
106
106
|
return Object.keys(where).every(key => row[key] === where[key]);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
// Alias for consistency with cache wrapper
|
|
110
|
+
_matchesWhere(row, where) {
|
|
111
|
+
return this._matches(row, where);
|
|
112
|
+
}
|
|
113
|
+
|
|
109
114
|
// --- GENEL (PUBLIC) API ---
|
|
110
115
|
|
|
111
116
|
async ensureTable(table) {
|
|
@@ -214,6 +219,60 @@ class JsonDatabase extends IDatabase{
|
|
|
214
219
|
});
|
|
215
220
|
}
|
|
216
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Numerik alanları artırır (increment).
|
|
224
|
+
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
225
|
+
* @param {object} increments - Artırılacak alanlar ve miktarları.
|
|
226
|
+
* @param {object} where - Güncelleme koşulları.
|
|
227
|
+
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
228
|
+
*/
|
|
229
|
+
async increment(table, increments, where = {}) {
|
|
230
|
+
await this.ensureTable(table);
|
|
231
|
+
return this._queueRequest(() => {
|
|
232
|
+
let affectedCount = 0;
|
|
233
|
+
this.db[table].forEach(row => {
|
|
234
|
+
if (this._matchesWhere(row, where)) {
|
|
235
|
+
for (const [field, value] of Object.entries(increments)) {
|
|
236
|
+
if (typeof row[field] === 'number') {
|
|
237
|
+
row[field] += value;
|
|
238
|
+
} else {
|
|
239
|
+
row[field] = value; // Eğer field sayı değilse, yeni değeri ata
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
affectedCount++;
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
return affectedCount;
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Numerik alanları azaltır (decrement).
|
|
251
|
+
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
252
|
+
* @param {object} decrements - Azaltılacak alanlar ve miktarları.
|
|
253
|
+
* @param {object} where - Güncelleme koşulları.
|
|
254
|
+
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
255
|
+
*/
|
|
256
|
+
async decrement(table, decrements, where = {}) {
|
|
257
|
+
await this.ensureTable(table);
|
|
258
|
+
return this._queueRequest(() => {
|
|
259
|
+
let affectedCount = 0;
|
|
260
|
+
this.db[table].forEach(row => {
|
|
261
|
+
if (this._matchesWhere(row, where)) {
|
|
262
|
+
for (const [field, value] of Object.entries(decrements)) {
|
|
263
|
+
if (typeof row[field] === 'number') {
|
|
264
|
+
row[field] -= value;
|
|
265
|
+
} else {
|
|
266
|
+
row[field] = -value; // Eğer field sayı değilse, negatif değeri ata
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
affectedCount++;
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
return affectedCount;
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
217
276
|
async close() {
|
|
218
277
|
await this._saveNow();
|
|
219
278
|
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
class MigrationManager {
|
|
5
|
+
constructor(database, options = {}) {
|
|
6
|
+
this.db = database;
|
|
7
|
+
this.migrationsDir = options.migrationsDir || './migrations';
|
|
8
|
+
this.migrationsTable = options.migrationsTable || 'migrations';
|
|
9
|
+
this.ensureMigrationsDir();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
ensureMigrationsDir() {
|
|
13
|
+
if (!fs.existsSync(this.migrationsDir)) {
|
|
14
|
+
fs.mkdirSync(this.migrationsDir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async ensureMigrationsTable() {
|
|
19
|
+
try {
|
|
20
|
+
// Migrations tablosu var mı kontrol et
|
|
21
|
+
await this.db.selectOne(this.migrationsTable, {});
|
|
22
|
+
} catch (error) {
|
|
23
|
+
// Tablo yoksa oluştur
|
|
24
|
+
const createTableSQL = `
|
|
25
|
+
CREATE TABLE IF NOT EXISTS ${this.migrationsTable} (
|
|
26
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
27
|
+
name VARCHAR(255) NOT NULL UNIQUE,
|
|
28
|
+
executed_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
29
|
+
)
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
// SQLite, MySQL, PostgreSQL için farklı SQL'ler
|
|
33
|
+
if (this.db.constructor.name === 'MySQLDatabase') {
|
|
34
|
+
await this.db.query(createTableSQL.replace('AUTOINCREMENT', 'AUTO_INCREMENT'));
|
|
35
|
+
} else if (this.db.constructor.name === 'PostgreSQLDatabase') {
|
|
36
|
+
const pgSQL = `
|
|
37
|
+
CREATE TABLE IF NOT EXISTS ${this.migrationsTable} (
|
|
38
|
+
id SERIAL PRIMARY KEY,
|
|
39
|
+
name VARCHAR(255) NOT NULL UNIQUE,
|
|
40
|
+
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
41
|
+
)
|
|
42
|
+
`;
|
|
43
|
+
await this.db.query(pgSQL);
|
|
44
|
+
} else {
|
|
45
|
+
// SQLite
|
|
46
|
+
await this.db.query(createTableSQL);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
createMigration(name, description = '') {
|
|
52
|
+
const timestamp = Date.now();
|
|
53
|
+
const filename = `${timestamp}_${name}.js`;
|
|
54
|
+
const filePath = path.join(this.migrationsDir, filename);
|
|
55
|
+
|
|
56
|
+
const template = `// Migration: ${name}
|
|
57
|
+
// Description: ${description}
|
|
58
|
+
// Created: ${new Date().toISOString()}
|
|
59
|
+
|
|
60
|
+
module.exports = {
|
|
61
|
+
async up(db) {
|
|
62
|
+
// Migration işlemlerini buraya yazın
|
|
63
|
+
// Örnek:
|
|
64
|
+
// await db.query(\`
|
|
65
|
+
// CREATE TABLE users (
|
|
66
|
+
// id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
67
|
+
// name VARCHAR(255) NOT NULL,
|
|
68
|
+
// email VARCHAR(255) UNIQUE NOT NULL
|
|
69
|
+
// )
|
|
70
|
+
// \`);
|
|
71
|
+
|
|
72
|
+
console.log('Migration ${name} executed (up)');
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
async down(db) {
|
|
76
|
+
// Rollback işlemlerini buraya yazın
|
|
77
|
+
// Örnek:
|
|
78
|
+
// await db.query('DROP TABLE IF EXISTS users');
|
|
79
|
+
|
|
80
|
+
console.log('Migration ${name} rolled back (down)');
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
fs.writeFileSync(filePath, template);
|
|
86
|
+
console.log(`Migration oluşturuldu: ${filename}`);
|
|
87
|
+
return filename;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getMigrationFiles() {
|
|
91
|
+
const files = fs.readdirSync(this.migrationsDir)
|
|
92
|
+
.filter(file => file.endsWith('.js'))
|
|
93
|
+
.sort();
|
|
94
|
+
|
|
95
|
+
return files.map(file => ({
|
|
96
|
+
name: file,
|
|
97
|
+
path: path.join(this.migrationsDir, file)
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async getExecutedMigrations() {
|
|
102
|
+
await this.ensureMigrationsTable();
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const executed = await this.db.select(this.migrationsTable, {});
|
|
106
|
+
return executed.map(row => row.name);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error('Executed migrations alınırken hata:', error);
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async getPendingMigrations() {
|
|
114
|
+
const allMigrations = this.getMigrationFiles();
|
|
115
|
+
const executedMigrations = await this.getExecutedMigrations();
|
|
116
|
+
|
|
117
|
+
return allMigrations.filter(migration =>
|
|
118
|
+
!executedMigrations.includes(migration.name)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async runMigration(migrationFile, direction = 'up') {
|
|
123
|
+
try {
|
|
124
|
+
delete require.cache[require.resolve(migrationFile.path)];
|
|
125
|
+
const migration = require(migrationFile.path);
|
|
126
|
+
|
|
127
|
+
if (typeof migration[direction] !== 'function') {
|
|
128
|
+
throw new Error(`Migration ${migrationFile.name} has no ${direction} method`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
await migration[direction](this.db);
|
|
132
|
+
|
|
133
|
+
if (direction === 'up') {
|
|
134
|
+
await this.db.insert(this.migrationsTable, {
|
|
135
|
+
name: migrationFile.name
|
|
136
|
+
});
|
|
137
|
+
} else if (direction === 'down') {
|
|
138
|
+
await this.db.delete(this.migrationsTable, {
|
|
139
|
+
name: migrationFile.name
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
console.log(`✅ Migration ${migrationFile.name} (${direction}) başarılı`);
|
|
144
|
+
return true;
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(`❌ Migration ${migrationFile.name} (${direction}) hatası:`, error);
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async migrate() {
|
|
152
|
+
const pending = await this.getPendingMigrations();
|
|
153
|
+
|
|
154
|
+
if (pending.length === 0) {
|
|
155
|
+
console.log('✅ Tüm migration\'lar güncel');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.log(`🔄 ${pending.length} migration çalıştırılacak...`);
|
|
160
|
+
|
|
161
|
+
for (const migration of pending) {
|
|
162
|
+
await this.runMigration(migration, 'up');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.log('✅ Tüm migration\'lar tamamlandı');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async rollback(steps = 1) {
|
|
169
|
+
const executed = await this.getExecutedMigrations();
|
|
170
|
+
|
|
171
|
+
if (executed.length === 0) {
|
|
172
|
+
console.log('❌ Rollback yapılacak migration yok');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const allMigrations = this.getMigrationFiles();
|
|
177
|
+
const toRollback = executed
|
|
178
|
+
.slice(-steps)
|
|
179
|
+
.reverse()
|
|
180
|
+
.map(name => allMigrations.find(m => m.name === name))
|
|
181
|
+
.filter(Boolean);
|
|
182
|
+
|
|
183
|
+
console.log(`🔄 ${toRollback.length} migration rollback edilecek...`);
|
|
184
|
+
|
|
185
|
+
for (const migration of toRollback) {
|
|
186
|
+
await this.runMigration(migration, 'down');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
console.log('✅ Rollback tamamlandı');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async status() {
|
|
193
|
+
const allMigrations = this.getMigrationFiles();
|
|
194
|
+
const executedMigrations = await this.getExecutedMigrations();
|
|
195
|
+
|
|
196
|
+
console.log('\n📋 Migration Durumu:');
|
|
197
|
+
console.log('==================');
|
|
198
|
+
|
|
199
|
+
if (allMigrations.length === 0) {
|
|
200
|
+
console.log('❌ Migration dosyası bulunamadı');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
allMigrations.forEach(migration => {
|
|
205
|
+
const status = executedMigrations.includes(migration.name) ? '✅ Executed' : '⏳ Pending';
|
|
206
|
+
console.log(`${status} ${migration.name}`);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const pendingCount = allMigrations.length - executedMigrations.length;
|
|
210
|
+
console.log(`\n📊 Toplam: ${allMigrations.length}, Executed: ${executedMigrations.length}, Pending: ${pendingCount}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async reset() {
|
|
214
|
+
const executed = await this.getExecutedMigrations();
|
|
215
|
+
|
|
216
|
+
if (executed.length === 0) {
|
|
217
|
+
console.log('❌ Reset edilecek migration yok');
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
console.log(`🔄 ${executed.length} migration reset edilecek...`);
|
|
222
|
+
await this.rollback(executed.length);
|
|
223
|
+
console.log('✅ Tüm migration\'lar reset edildi');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module.exports = MigrationManager;
|
package/database/mongodb.js
CHANGED
|
@@ -150,6 +150,51 @@ class MongoDBDatabase extends IDatabase{
|
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Numerik alanları artırır (increment).
|
|
155
|
+
* @param {string} collection - Verinin güncelleneceği koleksiyon adı.
|
|
156
|
+
* @param {object} increments - Artırılacak alanlar ve miktarları.
|
|
157
|
+
* @param {object} where - Güncelleme koşulları.
|
|
158
|
+
* @returns {Promise<number>} Etkilenen belge sayısı.
|
|
159
|
+
*/
|
|
160
|
+
async increment(collection, increments, where = {}) {
|
|
161
|
+
return this._queueRequest(async () => {
|
|
162
|
+
await this.ensureCollection(collection);
|
|
163
|
+
const db = await this._connectionPromise;
|
|
164
|
+
const incObject = {};
|
|
165
|
+
|
|
166
|
+
for (const [field, value] of Object.entries(increments)) {
|
|
167
|
+
incObject[field] = value;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const result = await db.collection(collection).updateMany(where, { $inc: incObject });
|
|
171
|
+
return result.modifiedCount;
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Numerik alanları azaltır (decrement).
|
|
177
|
+
* @param {string} collection - Verinin güncelleneceği koleksiyon adı.
|
|
178
|
+
* @param {object} decrements - Azaltılacak alanlar ve miktarları.
|
|
179
|
+
* @param {object} where - Güncelleme koşulları.
|
|
180
|
+
* @returns {Promise<number>} Etkilenen belge sayısı.
|
|
181
|
+
*/
|
|
182
|
+
async decrement(collection, decrements, where = {}) {
|
|
183
|
+
return this._queueRequest(async () => {
|
|
184
|
+
await this.ensureCollection(collection);
|
|
185
|
+
const db = await this._connectionPromise;
|
|
186
|
+
const incObject = {};
|
|
187
|
+
|
|
188
|
+
// Decrement için negatif değerler kullanıyoruz
|
|
189
|
+
for (const [field, value] of Object.entries(decrements)) {
|
|
190
|
+
incObject[field] = -value;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const result = await db.collection(collection).updateMany(where, { $inc: incObject });
|
|
194
|
+
return result.modifiedCount;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
153
198
|
async close() {
|
|
154
199
|
await this.client.close();
|
|
155
200
|
}
|
package/database/mysql.js
CHANGED
|
@@ -460,6 +460,67 @@ class MySQLDatabase extends IDatabase{
|
|
|
460
460
|
}
|
|
461
461
|
return value;
|
|
462
462
|
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* WHERE clause oluşturur
|
|
466
|
+
* @param {object} where - WHERE koşulları
|
|
467
|
+
* @returns {object} - whereClause string ve values array
|
|
468
|
+
*/
|
|
469
|
+
buildWhereClause(where = {}) {
|
|
470
|
+
const conditions = Object.keys(where);
|
|
471
|
+
if (conditions.length === 0) {
|
|
472
|
+
return { whereClause: '', values: [] };
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const whereClause = ' WHERE ' + conditions.map(key => `\`${key}\` = ?`).join(' AND ');
|
|
476
|
+
const values = Object.values(where).map(v => this._serializeValue(v));
|
|
477
|
+
|
|
478
|
+
return { whereClause, values };
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Numerik alanları artırır (increment).
|
|
483
|
+
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
484
|
+
* @param {object} increments - Artırılacak alanlar ve miktarları.
|
|
485
|
+
* @param {object} where - Güncelleme koşulları.
|
|
486
|
+
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
487
|
+
*/
|
|
488
|
+
async increment(table, increments, where = {}) {
|
|
489
|
+
const incrementClauses = Object.keys(increments).map(field =>
|
|
490
|
+
`${field} = ${field} + ?`
|
|
491
|
+
).join(', ');
|
|
492
|
+
|
|
493
|
+
const incrementValues = Object.values(increments);
|
|
494
|
+
const { whereClause, values: whereValues } = this.buildWhereClause(where);
|
|
495
|
+
|
|
496
|
+
const sql = `UPDATE ${table} SET ${incrementClauses}${whereClause}`;
|
|
497
|
+
const allValues = [...incrementValues, ...whereValues];
|
|
498
|
+
|
|
499
|
+
const [result] = await this.connection.execute(sql, allValues);
|
|
500
|
+
return result.affectedRows;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Numerik alanları azaltır (decrement).
|
|
505
|
+
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
506
|
+
* @param {object} decrements - Azaltılacak alanlar ve miktarları.
|
|
507
|
+
* @param {object} where - Güncelleme koşulları.
|
|
508
|
+
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
509
|
+
*/
|
|
510
|
+
async decrement(table, decrements, where = {}) {
|
|
511
|
+
const decrementClauses = Object.keys(decrements).map(field =>
|
|
512
|
+
`${field} = ${field} - ?`
|
|
513
|
+
).join(', ');
|
|
514
|
+
|
|
515
|
+
const decrementValues = Object.values(decrements);
|
|
516
|
+
const { whereClause, values: whereValues } = this.buildWhereClause(where);
|
|
517
|
+
|
|
518
|
+
const sql = `UPDATE ${table} SET ${decrementClauses}${whereClause}`;
|
|
519
|
+
const allValues = [...decrementValues, ...whereValues];
|
|
520
|
+
|
|
521
|
+
const [result] = await this.connection.execute(sql, allValues);
|
|
522
|
+
return result.affectedRows;
|
|
523
|
+
}
|
|
463
524
|
}
|
|
464
525
|
|
|
465
526
|
module.exports = MySQLDatabase;
|
package/database/pg.js
CHANGED
|
@@ -458,6 +458,70 @@ class PostgreSQLDatabase extends IDatabase {
|
|
|
458
458
|
// No need for manual JSON parsing unlike MySQL
|
|
459
459
|
return value;
|
|
460
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
|
+
}
|
|
461
525
|
}
|
|
462
526
|
|
|
463
527
|
module.exports = PostgreSQLDatabase;
|