-- _helpers.sql — إجراءات ترحيل قابلة لإعادة التشغيل -- -- ‏المشكلة: ALTER TABLE ... ADD COLUMN في MySQL يُجهض **كل** الجملة عند -- ‏أول عمود مكرّر. فإعادة تشغيل ترحيل نُفِّذ جزئياً تفشل، وإعادة تشغيل -- ‏ترحيل نُفِّذ كاملاً تفشل أيضاً — بلا أن تعرف أيّهما. -- -- ‏هذا لدغ نشرَ سيرو ثلاث مرات في يوم واحد، ويزداد سوءاً مع تعدد النسخ -- ‏(intaleq / tripz / siro) حيث لا أحد يتذكّر ما نُفِّذ أين. -- -- ‏الحل: إجراءات تفحص information_schema أولاً فتتخطّى الموجود بصمت. -- -- ‏شغّل هذا الملف مرة واحدة على كل قاعدة قبل أي ترحيل يستخدمه. DELIMITER // DROP PROCEDURE IF EXISTS `siro_add_column` // /** * ‏يضيف عموداً إن لم يكن موجوداً. آمن لإعادة التشغيل. * * ‏مثال: * CALL siro_add_column('ride', 'driverArrivedAt', * 'DATETIME NULL DEFAULT NULL COMMENT ''لحظة الوصول'''); */ CREATE PROCEDURE `siro_add_column`( IN p_table VARCHAR(64), IN p_column VARCHAR(64), IN p_definition TEXT ) BEGIN IF NOT EXISTS ( SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = p_table AND COLUMN_NAME = p_column ) THEN SET @ddl = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_definition); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; SELECT CONCAT('أُضيف: ', p_table, '.', p_column) AS result; ELSE SELECT CONCAT('موجود مسبقاً: ', p_table, '.', p_column) AS result; END IF; END // DROP PROCEDURE IF EXISTS `siro_add_index` // /** * ‏يضيف فهرساً إن لم يكن موجوداً. * CALL siro_add_index('driver_orders', 'idx_order', '(`order_id`)'); */ CREATE PROCEDURE `siro_add_index`( IN p_table VARCHAR(64), IN p_index VARCHAR(64), IN p_columns TEXT ) BEGIN IF NOT EXISTS ( SELECT 1 FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = p_table AND INDEX_NAME = p_index ) THEN SET @ddl = CONCAT('ALTER TABLE `', p_table, '` ADD INDEX `', p_index, '` ', p_columns); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; SELECT CONCAT('أُضيف فهرس: ', p_table, '.', p_index) AS result; ELSE SELECT CONCAT('فهرس موجود مسبقاً: ', p_table, '.', p_index) AS result; END IF; END // DELIMITER ;