diff --git a/README.ar.md b/README.ar.md index 88e0172..76cc6ec 100644 --- a/README.ar.md +++ b/README.ar.md @@ -1,4 +1,5 @@ # صـفوف (Rows) + [[English]](README.md) مكتبة للتعامل مع قواعد البيانات وتحقيق ال ORM (ربط الأغراض العلائقي) للغة الأسس. @@ -359,7 +360,6 @@ for i = 0, i < data.getLength(), i = i + 1 { ``` - ### استعمال خاصية المطابقة (ORM)
@@ -537,7 +537,7 @@ func printRows (r: Array[SrdRef[Car]]) { * إضافة مبدل يقابل صنف بيانات الحقل للمتغيرات. * إضافة المبدلات المتعلقة بالفهرسة والقيمة المبدئية والحقول المطلوبة إن وجد. -مثال: +مثال:
@@ -654,29 +654,100 @@ class ConnectionParams { def port: int = 0; } ``` + يحتوي هذا الصنف على المعلومات اللازمة للاتصال بقاعدة البيانات. -`اسم_قاعدة_البيانات` (`dbName`) اسم قاعدة البيانات التي نرغب بالاتصال بها. +#### اسم_قاعدة_البيانات (dbName) + +
+ +``` +عرف اسم_قاعدة_البيانات: نـص = "" +``` + +
+ +``` +def dbName: String = "" +``` + +اسم قاعدة البيانات التي نرغب بالاتصال بها. + +#### اسم_المستخدم (userName) + +
+ +``` +عرف اسم_المستخدم: نـص = "" +``` + +
+ +``` +def userName: String = "" +``` + +اسم المستخدم الخاص بحسابنا في قاعدة البيانات. + +#### كلمة_السر (password) + +
+ +``` +عرف كلمة_السر: نـص = "" +``` + +
+ +``` +def password: String = "" +``` + +كلمة سر الحساب الخاص بنا في قاعدة البيانات. + +#### عنوان_الخادم (host) + +
+ +``` + عرف عنوان_الخادم: نـص = "" +``` + +
+ +``` +def host: String = "" +``` + +عنوان الخادم الذي تعمل قاعدة البيانات عليه. + +#### المنفذ (port) + +
-`اسم_المستخدم` (`userName`) اسم المستخدم الخاص بحسابنا في قاعدة البيانات. +``` +عرف المنفذ: صحيح = 0 +``` -`كلمة_السر` (`password`) كلمة سر الحساب الخاص بنا في قاعدة البيانات. +
-`عنوان_الخادم` (`host`) عنوان الخادم الذي تعمل قاعدة البيانات عليه. +``` +def port: int = 0 +``` -`المنفذ` (`port`) المنفذ في الخادم الذي عن طريقه يمكن الوصول إلى قاعدة البيانات. +المنفذ في الخادم الذي عن طريقه يمكن الوصول إلى قاعدة البيانات. -### الصنف إنـشاء جدول (CreateTable) +### الصنف إنـشاء_جدول (CreateTable)
``` صنف إنـشاء_جدول { - عرف الاسم = نـص؛ - عرف جديد_فقط = ثـنائي؛ - عرف الحقول = تـطبيق[نـص، سـندنا[حـقل]]؛ - عرف الفهرس_الرئيسي = مـصفوفة[نـص]؛ - عرف فهارس_الوصل = مصفوفة[سـندنا[فـهرس_وصل]]؛ + عملية هذا.الاسم = نـص؛ + عملية هذا.جديد_فقط = ثـنائي؛ + عملية هذا.الحقول = تـطبيق[نـص، سـندنا[حـقل]]؛ + عملية هذا.الفهرس_الرئيسي = مـصفوفة[نـص]؛ + عملية هذا.فهارس_الوصل = مـصفوفة[سـندنا[فـهرس_وصل]]؛ } ``` @@ -691,18 +762,84 @@ class CreateTable { handler this.foreignKeys = Array[SrdRef[ForeignKey]]; } ``` + صنف يستعمل لإنشاء جدول حسب المعلومات التي يحويها. -`الاسم` (`name`) اسم الجدول +#### الاسم (name) + +
+ +``` +عملية هذا.الاسم = نـص؛ +``` +
+ +``` +handler this.name = String; +``` + +اسم الجدول. + +#### جديد_فقط (notExists) + +
+ +``` +عملية هذا.جديد_فقط = ثـنائي؛ +``` +
+ +``` +handler this.notExists = Bool; +``` + +متغير يحدد فيما إذا كنا نريد إنشاء الجدول فقط في حال لم يكن موجود مسبقاً. + +#### الحقول (columns) + +
+ +``` +عملية هذا.الحقول = تـطبيق[نـص، سـندنا[حـقل]]؛ +``` +
+ +``` +handler this.columns = Map[String, SrdRef[Column]]; +``` + +تـطبيق يربط بين اسم حقل و المعلومات الخاص به ضمن الصنف `Column`. + +#### الفهرس_الرئيسي (primaryKey) + +
+ +``` +عملية هذا.الفهرس_الرئيسي = مـصفوفة[نـص]؛ +``` + +
+ +``` +handler this.primaryKey = Array[String]; +``` -`جديد_فقط` (`notExists`) متغير يحدد فيما إذا كنا نريد إنشاء الجدول فقط في حال لم يكن موجود مسبقاً. +الفهرس الرئيسي للجدول. -`الحقول` (`columns`) تـطبيق يربط بين اسم حقل و المعلومات الخاص به ضمن الصنف `Column`. +#### فهارس_الوصل (foreignKeys) + +
-`الفهرس_الرئيسي` (`primaryKey`) الفهرس الرئيسي للجدول. +``` +عملية هذا.فهارس_الوصل = مـصفوفة[سـندنا[فـهرس_وصل]]؛ +``` +
-`فهارس_الوصل` (`foreignKeys`) فهارس الوصل و هي تعرف ارتباطات الجدول مع الجداول الأخرى. +``` +handler this.foreignKeys = Array[SrdRef[ForeignKey]]; +``` +فهارس الوصل و هي تعرف ارتباطات الجدول مع الجداول الأخرى. ### الصنف حـذف (Delete) @@ -710,8 +847,8 @@ class CreateTable { ``` صنف حـذف { - عرف الجدول = نـص؛ - عرف الشرط(عبارة: مؤشر[مـحرف]، معطيات: ...أي_معطيات_أخرى)؛ + عملية هذا.الجدول = نـص؛ + عملية هذا.الشرط(عبارة: مـؤشر_محارف، معطيات: ...أيما)؛ } ``` @@ -725,9 +862,35 @@ class Delete { ``` صنف يستعمل لحذف أسطر من جدول بناء على شرط معين. -`الجدول` (`table`) اسم الجدول. +#### الجدول (table) + +
+``` +عملية هذا.الجدول = نـص؛ +``` +
+ +``` +handler this.table = String; +``` + +اسم الجدول. + +#### الشرط (condition) + +
+ +``` +عملية هذا.الشرط(عبارة: مـؤشر_محارف، معطيات: ...أيما)؛ +``` + +
+ +``` +handler this.condition(statement: CharsPtr, args: ...any); +``` -`الشرط` (`condition`) الشرط الذي تم الحذف على أساسه. +الشرط الذي تم الحذف على أساسه. ### الصنف قـيمة (Value) @@ -777,9 +940,9 @@ class Value { ``` صنف إدخـال { - عرف الجدول = نـض؛ - عرف البيانات = مـصفوفة[قـيمة]؛ - عرف الحقول = مـصفوفة[نـص]؛ + عملية هذا.الجدول = نـص؛ + عملية هذا.البيانات = مـصفوفة[قـيمة]؛ + عملية هذا.الحقول = مـصفوفة[نـص]؛ } ``` @@ -794,251 +957,566 @@ class Insert { ``` يستعمل هذا الصنف لإضافة سطر إلى جدول. -`الجدول` (`table`) اسم الجدول الذي نريد الإضافة إليه. - -`البيانات` (`data`) البيانات الخاصة بالسطر المراد إضافته. - -`الحقول` (`columns`) أسماء الأعمدة التي تتبع لها القيم في `البيانات`. - - -### الصنف جـلب (Select) +#### الجدول (table)
``` - صنف جـلب { - عرف الجدول = مـصفوفة[نـص]؛ - عرف الحقول = مـصفوفة[نـص]؛ - عرف الشرط(عبارة: مؤشر[مـحرف]، معطيات: ...أي_معطيات_أخرى)؛ - عرف الترتيب = مـصفوفة[نـص]؛ -} +عملية هذا.الجدول = نـص؛ ```
``` -class Select { - handler this.table = Array[String]; - handler this.fields = Array[String]; - handler this.condition(statement: CharsPtr, args: ...any); - handler this.orderBy = Array[String]; -} +handler this.table = String; ``` -يستعمل هذا الصنف لجلب أسطر من جدول في قاعدة البيانات. - -`الاسم` (`name`) اسم الجدول المراد جلب البيانات منه. -`الحقول` (`columns`) أسماء الأعمدة التي نرغب بجلب قيمها. +اسم الجدول الذي نريد الإضافة إليه. -`الشرط` (`condition`) الشرط الذي نريد للأسطر أن تحققه حتى يتم جلبها. - -`الترتيب` (`orderBy`) الترتيب المراد تطبيقه على الأسطر. - -### الصنف تـحديث (Update) +#### البيانات (data)
``` -صنف تـحديث { - عرف الجدول = نـص؛ - عرف البيانات = مـصفوفة[قـيمة]؛ - عرف الحقول = مـصفوفة[نـص]؛ - عرف الشرط(عبارة: مؤشر[مـحرف]، معطيات: ...أي_معطيات_أخرى)؛ -} +عملية هذا.البيانات = مـصفوفة[قـيمة]؛ ```
``` -class Update { - handler this.table = String; - handler this.data = Array[Value]; - handler this.columns = Array[String]; - handler this.condition(statement: CharsPtr, args: ...any); -} +handler this.data = Array[Value]; ``` -يستعمل هذا الصنف لتحديث سطر أو مجموعة أسطر في جدول في قاعدة البيانات. +البيانات الخاصة بالسطر المراد إضافته. -`الاسم` (`name`) اسم الجدول المراد تحديث أسطر فيه. +#### الحقول (columns) + +
+ +``` +عملية هذا.الحقول = مـصفوفة[نـص]؛ +``` -`البيانات` (`data`) القيم الجديدة التي نريد تحديث الأسطر بها. +
-`الحقول` (`columns`) الأعمدة التي نريد تحديث قيمها حسب القيم في `البيانات`. +``` +handler this.columns = Array[String]; +``` -`الشرط` (`condition`) الشرط الذي يجب على السطر تحقيقه حتى يتم تحديثه. +أسماء الأعمدة التي تتبع لها القيم في `البيانات`. -### الصنف حـقل (Column) +### الصنف جـلب (Select)
``` -صنف حـقل { - عرف الصنف = سـندنا[نـمط_البيانات]؛ - عرف إلزامي = ثـنائي؛ - عرف فريد = ثـنائي؛ - عرف القيمة_الافتراضية = نـص؛ - عرف التحقق(عبارة: مؤشر[مـحرف]، معطيات: ...أي_معطيات_أخرى)؛ + صنف جـلب { + عملية هذا.الجدول = مـصفوفة[نـص]؛ + عملية هذا.الحقول = مـصفوفة[نـص]؛ + عملية هذا.الشرط(عبارة: مـؤشر_محارف، معطيات: ...أيما)؛ + عملية هذا.الترتيب = مـصفوفة[نـص]؛ } ```
``` -class Column { - handler this.dataType = SrdRef[DataType]; - handler this.notNull = Bool; - handler this.unique = Bool; - handler this.default = String; - handler this.check(statement: CharsPtr, args: ...any); +class Select { + handler this.table = Array[String]; + handler this.fields = Array[String]; + handler this.condition(statement: CharsPtr, args: ...any); + handler this.orderBy = Array[String]; } ``` +يستعمل هذا الصنف لجلب أسطر من جدول في قاعدة البيانات. -يحمل هذا الصنف المعلومات الخاصة بالحقل. +#### الجدول (table) -`الصنف` (`dataType`) نمط البيانات التي سيتم تخزينها في هذا الحقل. +
-`إلزامي` (`notNull`) هل من الضروري وجود قيمة لهذا الحقل أم من الممكن أن يكون خالٍ. +``` +عملية هذا.الجدول = مـصفوفة[نـص]؛ +``` -`فريد` (`unique`) هل قيم هذا الحقل يحب أن تكون فريدة أم من الممكن أن يحمل سطران نفس القيمة في هذا العمود. +
-`القيمة_الافتراضية` (`default`) القيمة الافتراضية لهذا الحقل في حال لم يتم إعطاء قيمة. +``` +handler this.table = Array[String]; +``` -`التحقق` (`check`) التحقق الذي يجب تطبيقه قبل قبول قيمة لهذا الحقل. +اسم الجدول المراد جلب البيانات منه. -### الصنف اسـتعلام (Query) +#### الحقول (fields)
``` -صنف اسـتعلام { - عرف رتب: سند[نمط_هذا]؛ - عرف حيثما: ماكرو[هذا، شرط]؛ - عرف حدث: ماكرو[هذا، عبارة]؛ - عرف اجلب(): لـا_مضمون[مـصفوفة[سـندنا[جـدول]]]؛ - عرف احفظ(جدول: سند[جـدول]): لـا_مضمون[صـحيح]؛ - عرف احذف(جدول: سند[جـدول]): لـا_مضمون[صـحيح]؛ -} +عملية هذا.الحقول = مـصفوفة[نـص]؛ ```
``` -class Query [Model: type] { - handler [exp: ast] this.order:ref[this_type]; - @member macro where [this, condition]; - @member macro update [this, expression]; - handler this.select(): Possible[Array[SrdRef[Model]]]; - handler this.save(model: ref[Model]): Possible[Int]; - handler this.delete(model: ref[Model]): Possible[Int]; -} +handler this.fields = Array[String]; ``` -`رتب` (`order`) يستعمل لوضع الترتيب الخاص باستعلام. +أسماء الأعمدة التي نرغب بجلب قيمها. -`حيثما` (`where`) ماكرو يستعمل لوضع الشرط الخاص باستعلام. - -المعطيات: - -* `هذا` (`this`) سند إلى غرض من النمط استعلام. -* `شرط` (`condition`) الشرط المطلوب تطبيقه. +#### الشرط (condition) -`حدث` (`update`) ماكرو يستعمل لتنفيذ تعليمة تحديث على جدول. +
-المعطيات: +``` +عملية هذا.الشرط(عبارة: مـؤشر_محارف، معطيات: ...أيما)؛ +``` +
-* `هذا` (`this`) سند إلى غرض من النمط استعلام. -* `عبارة` (`expression`) العبارة الخاصة بالتحديث. +``` +handler this.condition(statement: CharsPtr, args: ...any); +``` -`اجلب` (`select`) يستعمل لجلب أسطر جدول ما. +الشرط الذي نريد للأسطر أن تحققه حتى يتم جلبها. -`احفظ` (`save`) يستعمل لحفظ سطر ما في الجدول. +#### الترتيب (orderBy) -المعطيات: +
-* `جدول` (`model`) سند إلى الجدول المراد حفظ السطر فيه. +``` +عملية هذا.الترتيب = مـصفوفة[نـص]؛ +``` -`احذف` (`delete`) يستعمل للحذف من الجدول. +
-المعطيات: +``` +handler this.orderBy = Array[String]; +``` -* `جدول` (`model`) سند إلى الجدول المراد حذف السطر فيه. +الترتيب المراد تطبيقه على الأسطر. -يستخدم هذا الصنف لتمكين جمع الخصائص المختلفة للاستعلام قبل تنفيذه، وفي العادة لا يحتاج المستخدم -لإنشاء كائنات من هذا الصنف يدويًا إنما باستخدام `قـاعدة_بيانات.من` (`Db.from`). مثلا: +### الصنف تـحديث (Update)
``` -قب.من[مـستخدم].حيثما[الاسم = معطى1].حدث[العنوان = معطى2]؛ +صنف تـحديث { + عملية هذا.الجدول = نـص؛ + عملية هذا.البيانات = مـصفوفة[قـيمة]؛ + عملية هذا.الحقول = مـصفوفة[نـص]؛ + عملية هذا.الشرط(عبارة: مـؤشر_محارف، معطيات: ...أيما)؛ +} ```
``` -db.from[User].where[name = arg1].update[address = arg2]; +class Update { + handler this.table = String; + handler this.data = Array[Value]; + handler this.columns = Array[String]; + handler this.condition(statement: CharsPtr, args: ...any); +} ``` -#### المطابقة الجزئية (LIKE) +يستعمل هذا الصنف لتحديث سطر أو مجموعة أسطر في جدول في قاعدة البيانات. -لإجراء مطابقة جزئية (ما يعادل عبارة `LIKE` في SQL)، يمكن استخدام العامل `::` في شرط `حيثما` (`where`). -يتبع النمط صيغة SQL LIKE حيث يطابق `%` أي سلسلة من المحارف. ويمكن استخدام الرمز `!` لتمثيل الرموز -الخاصة نفسها (% و _ و !) ضمن نمط البحث نفسه. +#### الجدول (table)
``` -د = قب.من[سـيارة].حيثما[الاسم :: "سيارة %"].اجلب()؛ +عملية هذا.الجدول = نـص؛ ```
``` -d = db.from[Car].where[name :: "Car %"].select(); +handler this.table = String; ``` -ملاحظة: بسبب أولوية العوامل في لغة الأسس، يجب استخدام الأقواس حول عبارة `::` عند دمجها مع شروط -أخرى في `حيثما` (`where`)، كما في المثال التالي: +اسم الجدول المراد تحديث أسطر فيه. + +#### البيانات (data)
``` -د = قب.من[سـيارة].حيثما[(الاسم :: "سيارة %") و السعر < الحد_الأقصى].اجلب()؛ +عملية هذا.البيانات = مـصفوفة[قـيمة]؛ ```
``` -d = db.from[Car].where[(name :: "Car %") and price < maxPrice].select(); +handler this.data = Array[Value]; ``` -بدون الأقواس حول المؤثر `::` ستحصل على خطأ في الترجمة لأن المترجم سيحاول تنفيذ عملية `و` (`and`) -أولاً. +القيم الجديدة التي نريد تحديث الأسطر بها. -### الصنف مـهيكل (SchemaBuilder) +#### الحقول (columns)
``` -صنف مـهيكل [هيكل: سند_شبم] { - عملية هذا.واكب(): سـندنا[خـطأ]؛ -} +عملية هذا.الحقول = مـصفوفة[نـص]؛ ```
``` -class SchemaBuilder [Model: type] { - handler this.migrate(): SrdRef[Error]; -} +handler this.columns = Array[String]; ``` -يستخدم قالب الأصناف هذا لمواكبة (migrate) قاعدة البيانات مع أصناف البيانات (models) المعرفة -في الشفرة المصدرية. يجب أن يكون معطى القالب إشارة إلى صنف بيانات أو إلى قائمة من الأصناف التي -تتشكل منها قاعدة البيانات. يتولى المهيكل مسؤولية إنشاء قاعدة البيانات أو تحديثها إلى آخر -إصدار عبر تنفيذ دالات المواكبة المطلوبة. +الأعمدة التي نريد تحديث قيمها حسب القيم في `البيانات`. -`واكب` هذه الدالة تواكب قاعدة البيانات مع أصناف البيانات المعرفة في الشفرة المصدرية، أو تنشئ +#### الشرط (condition) + +
+ +``` +عملية هذا.الشرط(عبارة: مـؤشر_محارف، معطيات: ...أيما)؛ +``` +
+ +``` +handler this.condition(statement: CharsPtr, args: ...any); +``` + +الشرط الذي يجب على السطر تحقيقه حتى يتم تحديثه. + +### الصنف حـقل (Column) + +
+ +``` +صنف حـقل { + عملية هذا.الصنف = سـندنا[صـنف_البيانات]؛ + عملية هذا.إلزامي = ثـنائي؛ + عملية هذا.فريد = ثـنائي؛ + عملية هذا.القيمة_الافتراضية = نـص؛ + عملية هذا.التحقق(عبارة: مـؤشر_محارف، معطيات: ...أيما)؛ +} +``` + +
+ +``` +class Column { + handler this.dataType = SrdRef[DataType]; + handler this.notNull = Bool; + handler this.unique = Bool; + handler this.default = String; + handler this.check(statement: CharsPtr, args: ...any); +} +``` + +يحمل هذا الصنف المعلومات الخاصة بالحقل. + +#### الصنف (dataType) + +
+ +``` + عملية هذا.الصنف = سـندنا[صـنف_البيانات]؛ +``` + +
+ +``` +handler this.dataType = SrdRef[DataType]; +``` + +نمط البيانات التي سيتم تخزينها في هذا الحقل. + +#### إلزامي (notNull) + +
+ +``` +عملية هذا.إلزامي = ثـنائي؛ +``` +
+ +``` +handler this.notNull = Bool; +``` + +هل من الضروري وجود قيمة لهذا الحقل أم من الممكن أن يكون خالٍ. + +#### فريد (unique) + +
+ +``` +عملية هذا.فريد = ثـنائي؛ +``` +
+ +``` +handler this.unique = Bool; +``` + +هل قيم هذا الحقل يحب أن تكون فريدة أم من الممكن أن يحمل سطران نفس القيمة في هذا العمود. + +#### القيمة_الافتراضية (default) + +
+ +``` +عملية هذا.القيمة_الافتراضية = نـص؛ +``` +
+ +``` +handler this.default = String; +``` + +القيمة الافتراضية لهذا الحقل في حال لم يتم إعطاء قيمة. + +#### التحقق (check) + +
+ +``` +عملية هذا.التحقق(عبارة: مـؤشر_محارف، معطيات: ...أيما)؛ +``` + +
+ +``` +handler this.check(statement: CharsPtr, args: ...any); +``` + +التحقق الذي يجب تطبيقه قبل قبول قيمة لهذا الحقل. + +### الصنف اسـتعلام (Query) + +
+ +``` +صنف اسـتعلام [جدول: صنف] { + عملية [تركيب: شبم] هذا.رتب: سند[هذا_الصنف]؛ + @عضو ماكرو حيثما [هذا، شرط]؛ + @عضو ماكرو حدث [هذا، عبارة]؛ + عملية هذا.اجلب(): لـا_مضمون[مـصفوفة[سـندنا[جـدول]]]؛ + عملية هذا.احفظ(جدول: سند[جـدول]): لـا_مضمون[صـحيح]؛ + عملية هذا.احذف(جدول: سند[جـدول]): لـا_مضمون[صـحيح]؛ +} +``` + +
+ +``` +class Query [Model: type] { + handler [exp: ast] this.order: ref[this_type]; + @member macro where [this, condition]; + @member macro update [this, expression]; + handler this.select(): Possible[Array[SrdRef[Model]]]; + handler this.save(model: ref[Model]): Possible[Int]; + handler this.delete(model: ref[Model]): Possible[Int]; +} +``` + +يستخدم هذا الصنف لتمكين جمع الخصائص المختلفة للاستعلام قبل تنفيذه، وفي العادة لا يحتاج المستخدم +لإنشاء كائنات من هذا الصنف يدويًا إنما باستخدام `قـاعدة_بيانات.من` (`Db.from`). مثلا: + +
+ +``` +قب.من[مـستخدم].حيثما[الاسم == معطى1].حدث[العنوان = معطى2]؛ +``` + +
+ +``` +db.from[User].where[name == arg1].update[address = arg2]; +``` + +#### رتب (order) + +
+ +``` +عملية [تركيب: شبم] هذا.رتب: سند[هذا_الصنف]؛ +``` + +
+ +``` +handler [exp: ast] this.order:ref[this_type]; +``` + +يستعمل لوضع الترتيب الخاص باستعلام. + +#### حيثما (where) + +
+ +``` +@عضو ماكرو حيثما [هذا، شرط]؛ +``` + +
+ +``` +@member macro where [this, condition]; +``` + +ماكرو يستعمل لوضع الشرط الخاص باستعلام. + +المعطيات: + +* `هذا` (`this`) سند إلى غرض من النمط استعلام. +* `شرط` (`condition`) الشرط المطلوب تطبيقه. + +#### حدث (update) + +
+ +``` +@عضو ماكرو حدث [هذا، عبارة]؛ +``` + +
+ +``` +@member macro update [this, expression]; +``` + +ماكرو يستعمل لتنفيذ تعليمة تحديث على جدول. + +المعطيات: + +* `هذا` (`this`) سند إلى غرض من النمط استعلام. +* `عبارة` (`expression`) العبارة الخاصة بالتحديث. + +#### اجلب (select) + +
+ +``` +عملية هذا.اجلب(): لـا_مضمون[مـصفوفة[سـندنا[جـدول]]]؛ +``` + +
+ +``` +handler this.select(): Possible[Array[SrdRef[Model]]]; +``` + +يستعمل لجلب أسطر جدول ما. + +#### احفظ (save) + +
+ +``` +عملية هذا.احفظ(جدول: سند[جـدول]): لـا_مضمون[صـحيح]؛ +``` +
+ +``` +handler this.save(model: ref[Model]): Possible[Int]; +``` + +يستعمل لحفظ سطر ما في الجدول. + +المعطيات: + +* `جدول` (`model`) سند إلى الجدول المراد حفظ السطر فيه. + +#### احذف (delete) + +
+ +``` +عملية هذا.احذف(جدول: سند[جـدول]): لـا_مضمون[صـحيح]؛ +``` + +
+ +``` +handler this.delete(model: ref[Model]): Possible[Int]; +``` + +يستعمل للحذف من الجدول. + +المعطيات: + +* `جدول` (`model`) سند إلى الجدول المراد حذف السطر فيه. + +#### المطابقة الجزئية (LIKE) + +لإجراء مطابقة جزئية (ما يعادل عبارة `LIKE` في SQL)، يمكن استخدام العامل `::` في شرط `حيثما` (`where`). +يتبع النمط صيغة SQL LIKE حيث يطابق `%` أي سلسلة من المحارف. ويمكن استخدام الرمز `!` لتمثيل الرموز +الخاصة نفسها (% و _ و !) ضمن نمط البحث نفسه. + +
+ +``` +د = قب.من[سـيارة].حيثما[الاسم :: "سيارة %"].اجلب()؛ +``` + +
+ +``` +d = db.from[Car].where[name :: "Car %"].select(); +``` + +ملاحظة: بسبب أولوية العوامل في لغة الأسس، يجب استخدام الأقواس حول عبارة `::` عند دمجها مع شروط +أخرى في `حيثما` (`where`)، كما في المثال التالي: + +
+ +``` +د = قب.من[سـيارة].حيثما[(الاسم :: "سيارة %") و السعر < الحد_الأقصى].اجلب()؛ +``` + +
+ +``` +d = db.from[Car].where[(name :: "Car %") and price < maxPrice].select(); +``` + +بدون الأقواس حول المؤثر `::` ستحصل على خطأ في الترجمة لأن المترجم سيحاول تنفيذ عملية `و` (`and`) +أولاً. + +### الصنف مـهيكل (SchemaBuilder) + +
+ +``` +صنف مـهيكل [هيكل: سند_شبم] { + عملية هذا.واكب(): سـندنا[خـطأ]؛ +} +``` + +
+ +``` +class SchemaBuilder [schema: ast_ref] { + handler this.migrate(): SrdRef[Error]; +} +``` + +يستخدم قالب الأصناف هذا لمواكبة (migrate) قاعدة البيانات مع أصناف البيانات (models) المعرفة +في الشفرة المصدرية. يجب أن يكون معطى القالب إشارة إلى صنف بيانات أو إلى قائمة من الأصناف التي +تتشكل منها قاعدة البيانات. يتولى المهيكل مسؤولية إنشاء قاعدة البيانات أو تحديثها إلى آخر +إصدار عبر تنفيذ دالات المواكبة المطلوبة. + +#### واكب (migrate) + +
+ +``` +عملية هذا.واكب(): سـندنا[خـطأ]؛ +``` + +
+ +``` +handler this.migrate(): SrdRef[Error]; +``` + +`واكب` هذه الدالة تواكب قاعدة البيانات مع أصناف البيانات المعرفة في الشفرة المصدرية، أو تنشئ قاعدة البيانات إن لم تكون موجودة بالأساس. عندما لا يكون الجدول موجودا في قاعدة البيانات ينشئه المهيكل من صنف البيانات مباشرة، وإن كان @@ -1056,13 +1534,14 @@ class SchemaBuilder [Model: type] {
``` - @migration[1, 2] - function migrateFromV1ToV2(db: ref[Db]): SrdRef[Error]; +@migration[1, 2] +function migrateFromV1ToV2(db: ref[Db]): SrdRef[Error]; ``` الدالة أعلاه تحدث الجدول من الإصدار 1 إلى الإصدار 2. يمكنك إضافة قائمة بالاعتماديات الخاصة بتلك -الدالة إلى المبدل `مواكبة` (`migration`) لضمان تنفيذ دالات المواكبة بالترتيب الصحيح. على سبيل -المثال: +الدالة إلى المبدل `مواكبة` (`migration`) لضمان تنفيذ دالات المواكبة بالترتيب الصحيح. + +علي سبيل المثال :
@@ -1074,8 +1553,8 @@ class SchemaBuilder [Model: type] {
``` - @migration[1, 2, { User: 3 }] - function migrateFromV1ToV2(db: ref[Db]): SrdRef[Error]; +@migration[1, 2, { User: 3 }] +function migrateFromV1ToV2(db: ref[Db]): SrdRef[Error]; ``` المثال أعلاه يخبر المهيكل أن ينفذ هذه الدالة عندما يكون الجدول `مـستخدم` (`User`) عن الإصدار 3. @@ -1089,10 +1568,6 @@ class SchemaBuilder [Model: type] { ### الصنف مـشغل (Driver) -هذا هو الصنف الأساسي لجميع مشغلات قواعد البيانات، وهو المسؤول عن جميع الاتصالات -مع قاعدة البيانات. يحتوي على العديد من الوظائف المجردة التي يستعملها الصنف `قـاعدة_بيانات` -ولن يحتاج المستخدم في العادة للتعامل مع أي من وظائف هذا الصنف عدا الوظائف المتعلقة بالاتصال. -
``` @@ -1119,6 +1594,105 @@ class Driver { } ``` +هذا هو الصنف الأساسي لجميع مشغلات قواعد البيانات، وهو المسؤول عن جميع الاتصالات +مع قاعدة البيانات. يحتوي على العديد من الوظائف المجردة التي يستعملها الصنف `قـاعدة_بيانات` +ولن يحتاج المستخدم في العادة للتعامل مع أي من وظائف هذا الصنف عدا الوظائف المتعلقة بالاتصال. + +#### اتصل (connect) + +
+ +``` +عملية هذا.اتصل(معطيات: سند[مـعطيات_الاتصال]): ثـنائي كمؤشر؛ +``` + +
+ +``` +handler this.connect(parmas: ref[ConnectionParams]): Bool as_ptr; +``` + +الاتصال بقاعدة البيانات. + +#### افصل (disconnect) + +
+ +``` +عملية هذا.افصل() كمؤشر؛ +``` + +
+ +``` +handler this.disconnect() as_ptr; +``` + +قطع الاتصال بقاعدة البيانات. + +#### أمتصل (isConnected) + +
+ +``` +عملية هذا.أمتصل(): ثـنائي كمؤشر؛ +``` + +
+ +``` +handler this.isConnected(): Bool as_ptr; +``` + +التحقق من الاتصال بقاعدة البيانات. + +#### هل_بدئ_الاتصال (isConnectionEstablished) + +
+ +``` +عملية هذا.هل_بدئ_الاتصال(): ثـنائي كمؤشر؛ +``` + +
+ +``` +handler this.isConnectionEstablished(): Bool as_ptr; +``` + +التحقق من أن الاتصال قد تم. + +#### هات_معطيات_الاتصال (getConnectionParams) + +
+ +``` +عملية هذا.هات_معطيات_الاتصال(): مـعطيات_الاتصال كمؤشر؛ +``` + +
+ +``` +handler this.getConnectionParams(): ConnectionParams as_ptr; +``` + +جلب معطيات الاتصال. + +#### هات_آخر_خطأ (getLastError) + +
+ +``` +عملية هذا.هات_آخر_خطأ(): نـص كمؤشر؛ +``` +
+ +``` +handler this.getLastError(): String as_ptr; +``` + +جلب رسالة آخر خطأ. + ### الصنف قـاعدة_بيانات (Db)
@@ -1135,16 +1709,16 @@ class Driver { عملية هذا.هيئ(مهيئ: مغلفة(سند[سـندنا[مـشغل]]))؛ عملية هذا.أمتصل(): ثـنائي؛ عملية هذا.هات_آخر_خطأ(): نـص؛ - عملية هذا.نفذ(اجلب: سند[اجـلب]): لـا_مضمون[مـصفوفة[مـصفوفة[نـص]]]؛ - عملية هذا.نفذ(تحديث: سند[تـحديث]): لـا_مضمون[صـحيح]؛ - عملية هذا.نفذ(أدخل: سند[احـشر]): لـا_مضمون[صـحيح]؛ - عملية هذا.نفذ(احذف: سند[احـذف]): لـا_مضمون[صـحيح]؛ - عملية هذا.نفذ(أنشئ_جـدول: سند[أنـشئ_جدول]): لـا_مضمون[صـحيح]؛ - عملية هذا.نفذ(عبارة: مؤشر[مـحرف]، معطيات: ...أيما): لـا_مضمون[صـحيح]؛ + عملية هذا.نفذ(جـلب: سند[جـلب]): لـا_مضمون[مـصفوفة[مـصفوفة[نـص]]]؛ + عملية هذا.نفذ(تحديث: سند[تحديث]): لـا_مضمون[صـحيح]؛ + عملية هذا.نفذ(إدخـال: سند[إدخـال]): لـا_مضمون[صـحيح]؛ + عملية هذا.نفذ(حـذف: سند[حـذف]): لـا_مضمون[صـحيح]؛ + عملية هذا.نفذ(إنـشاء_جدول: سند[إنـشاء_جدول]): لـا_مضمون[صـحيح]؛ + عملية هذا.نفذ(عبارة: مـؤشر_محارف معطيات: ...أيما): لـا_مضمون[صـحيح]؛ عملية هذا.نفذ_جلبا(عبارة: مـؤشر_محارف, معطيات: ...أيما): لـا_مضمون[مـصفوفة[مـصفوفة[بـعدم[نـص]]]]؛ - عملية هذا.[جـدول: نمط] من: اسـتعلام[جـدول]؛ - عملية هذا.[جـدول: نمط] احفظ(جدول: سند[جـدول])؛ - عملية هذا.[جـدول: نمط] مهيكل: مـهيكل[جـدول]؛ + عملية [جـدول: صنف] هذا.من: اسـتعلام[جـدول]؛ + عملية [جـدول: صنف] هذا.احفظ(جدول: سند[جـدول])؛ + عملية [جـدول: صنف] هذا.مهيكل: مـهيكل[جـدول]؛ } ``` @@ -1177,54 +1751,234 @@ class Db { يستعمل هذا الصنف لتنظيم الوصول إلى قاعدة البيانات و تنفيذ مختلف العمليات عليها. -`تدوين` (`logging`) إعطاء هذا المتغير قيمة 1 يجعل المكتبة تطبع عبارات SQL التي يتم تنفيذها. +#### تدوين (logging) + +
+ +``` +قـاعدة_بيانات.تدوين: ثـنائي; +``` + +
+ +``` +db.logging: Bool; +``` + +إعطاء هذا المتغير قيمة 1 يجعل المكتبة تطبع عبارات SQL التي يتم تنفيذها. + +#### انتظار_إعادة_الاتصال (reconnectionDelay) + +
+ +``` +قـاعدة_بيانات.انتظار_إعادة_الاتصال: طـبيعي; +``` + +
+ +``` +db.reconnectionDelay: Word; +``` -`انتظار_إعادة_الاتصال` (`reconnectionDelay`) الوقت بالمايكرو ثانية الذي تنتظره المكتبة عند انقطاع +الوقت بالمايكرو ثانية الذي تنتظره المكتبة عند انقطاع الاتصال بالخادم قبل معاودة الاتصال. -`عدد_محاولات_إعادة_الاتصال` (`reconnectionAttemptCount`) عدد محاولات إعادة الاتصال قبل أن تتوقف المكتبة +#### عدد_محاولات_إعادة_الاتصال (reconnectionAttemptCount) + +
+ +``` +قـاعدة_بيانات.عدد_محاولات_إعادة_الاتصال: صـحيح; +``` + +
+ +``` +db.reconnectionAttemptCount: Int; +``` + +عدد محاولات إعادة الاتصال قبل أن تتوقف المكتبة عن المحاولة وترجع إشعار خطأ. -`هيئ` (`init`) يهيئ قاعدة البيانات بالمشغل المعطى. نسخة المغلفة من هذه الدالة تستخدم لتمكين استخدام +#### ~هيئ (init~) + +
+ +``` +عملية هذا~هيئ(م: سـندنا[مـشغل])؛ +عملية هذا~هيئ(مهيئ: مغلفة(سند[سـندنا[مـشغل]]))؛ +``` + +
+ +``` +handler this~init(d: SrdRef[Driver]); +handler this~init(initializer: closure(ref[SrdRef[Driver]])); +``` + +يهيئ قاعدة البيانات بالمشغل المعطى. نسخة المغلفة من هذه الدالة تستخدم لتمكين استخدام كائن `قـاعدة_بيانات` من مسالك متعددة. تُستدعى الدالة لتهيئة مشغل جديد لكل مسلك جديد يستخدم قاعدة البيانات. -`أمتصل` (`isConnected`) يستعمل للتحقق فيما إذا كان هناك اتصال مع قاعدة البيانات. +#### هيئ (init) + +
+ +``` +عملية هذا.هيئ(م: سـندنا[مـشغل])؛ +عملية هذا.هيئ(مهيئ: مغلفة(سند[سـندنا[مـشغل]]))؛ +``` + +
+ +``` +handler this.init(d: SrdRef[Driver]); +handler this.init(initializer: closure(ref[SrdRef[Driver]])); +``` + +يهيئ قاعدة البيانات بالمشغل المعطى. نسخة المغلفة تستخدم لدعم المسالك المتعددة. + +#### أمتصل (isConnected) + +
+ +``` +عملية هذا.أمتصل(): ثـنائي؛ +``` + +
+ +``` +handler this.isConnected(): Bool; +``` + +يستعمل للتحقق فيما إذا كان هناك اتصال مع قاعدة البيانات. + +#### هات_آخر_خطأ (getLastError) + +
+ +``` +عملية هذا.هات_آخر_خطأ(): نـص؛ +``` + +
+ +``` +handler this.getLastError(): String; +``` + +يستعمل لجلب آخر خطأ. + +#### نفذ (exec) -`هات_آخر_خطأ` (`getLastError`) يستعمل لجلب آخر خطأ. +
+ +``` +عملية هذا.نفذ(جـلب: سند[جـلب]): لـا_مضمون[مـصفوفة[مـصفوفة[نـص]]]؛ +عملية هذا.نفذ(تحديث: سند[تحديث]): لـا_مضمون[صـحيح]؛ +عملية هذا.نفذ(إدخـال: سند[إدخـال]): لـا_مضمون[صـحيح]؛ +عملية هذا.نفذ(حـذف: سند[حـذف]): لـا_مضمون[صـحيح]؛ +عملية هذا.نفذ(إنـشاء_جدول: سند[إنـشاء_جدول]): لـا_مضمون[صـحيح]؛ +عملية هذا.نفذ(عبارة: مـؤشر_محارف معطيات: ...أيما): لـا_مضمون[صـحيح]؛ +``` + +
+ +``` +handler this.exec(select: ref[Select]): Possible[Array[Array[String]]]; +handler this.exec(update: ref[Update]): Possible[Int]; +handler this.exec(insert: ref[Insert]): Possible[Int]; +handler this.exec(delete: ref[Delete]): Possible[Int]; +handler this.exec(createTable: ref[CreateTable]): Possible[Int]; +handler this.exec(statement: CharsPtr, args: ...any): Possible[Int]; +``` `نفذ` (`exec`) يستعمل لتنفيذ استعلام ما، و له نسخة لكل نوع من أنواع الاستعلامات بالإضافة إلى نسخة لتنفيذ عبارات SQL خام. نسخة تنفيذ عبارات SQL تفصل الهيكل الرئيسي لعبارة SQL عن المعطيات التي يمررها المستخدم كمعطيات لاحظة لدالة `نفذ` بطريقة مشابهة لعمل دالة الطباعة. تستبدل الدالة الرموز البادئة ب% في SQL بقيمة من قائمة المعطيات تطابق الصنف المحدد. الرمز % يتبعه محرف يدل على صنف القيمة المعطاة، وهي كالتالي: -* مـؤشر_محارف (CharsPtr) لاسم حقل أو جدول: %n -* نـص (String): %s -* مـؤشر_محارف (CharsPtr): %p -* صـحيح (Int): %i -* صـحيح[64] (Int[64]): %l -* عـائم (Float): %f -* عـائم[64] (Float[64]): %d -* مـصفوفة[نـص] (Array[String]): %as -* مـصفوفة[مـؤشر_محارف] (Array[CharsPtr]): %ap -* مـصفوفة[صـحيح] (Array[Int]): %ai -* مـصفوفة[صـحيح[64]] (Array[Int[64]]): %al -* مـصفوفة[عـائم] (Array[Float]): %af -* مـصفوفة[عـائم[64]] (Array[Float[64]]): %ad - -`نفذ_جلبا` مشابهة لدالة `نفذ` الخاصة بتنفيذ عبارات SQL خامة لكنها تستخدم مع العبارات + +* ` مـؤشر_محارف` (`CharsPtr`): `%n` +* `نـص` (`String`): `%s` +* `مـؤشر_محارف` (`CharsPtr`): `%p` +* `صـحيح` (`Int`): `%i` +* `صـحيح[64]` (`Int[64]`): `%l` +* `عـائم` (`Float`): `%f` +* `عـائم[64]` (`Float[64]`): `%d` +* `مـصفوفة[نـص]` (`Array[String]`): `%as` +* `مـصفوفة[مـؤشر_محارف]` (`Array[CharsPtr]`): `%ap` +* `مـصفوفة[صـحيح]` (`Array[Int]`): `%ai` +* `مـصفوفة[صـحيح[64]]` (`Array[Int[64]]`): `%al` +* `مـصفوفة[عـائم]` (`Array[Float]`): `%af` +* `مـصفوفة[عـائم[64]]` (`Array[Float[64]]`): `%ad` + +#### نفذ_جلبا (execSelect) + +
+ +``` +عملية هذا.نفذ_جلبا(عبارة: مـؤشر_محارف, معطيات: ...أيما): لـا_مضمون[مـصفوفة[مـصفوفة[بـعدم[نـص]]]]؛ +``` + +
+ +``` +handler this.execSelect(statement: CharsPtr, args: ...any): Possible[Array[Array[Nullable[String]]]]; +``` + +`نفذ_جلبا` مشابهة لدالة `نفذ` الخاصة بتنفيذ عبارات SQL لكنها تستخدم مع العبارات التي تجلب بيانات. -آخر نسخة من هذه الدالة تقوم باستقبال شفرة sql خام و تقوم بتنفيذ هذه الشفرة. -من المفيد وجود هذه الدالة لتنفيذ الشفرات المعقدة. +#### من (from) + +
+ +``` +عملية [جـدول: صنف] هذا.من: اسـتعلام[جـدول]؛ +``` + +
+ +``` +handler [Model: type] this.from: Query[Model]; +``` + +يستعمل لإعادة استعلام بناء على المعلومات في هذا الصنف. -عند تنفيذ عمليات كتابة (إدخال قيد أو تحديث قيد أو حذف قيد) ترجع دالة `نفذ` عدد القيود المتأثرة بالعملية. +#### احفظ (save) + +
-`من` (`from`) يستعمل لإعادة استعلام بناء على المعلومات في هذا الصنف. +``` +عملية [جـدول: صنف] هذا.احفظ(جدول: سند[جـدول])؛ +``` -`احفظ` (`save`) يستعمل لاستدعاء الوظيفة `احفظ` في الصنف `اسـتعلام`. +
-`مهيكل` (`schemaBuilder`) يستعمل لإعادة مهيكل بناء على المعلومات في هذا الصنف. +``` +handler [Model: type] this.save(model: ref[Model]); +``` + +يستعمل لاستدعاء الوظيفة `احفظ` في الصنف `اسـتعلام`. + +#### مهيكل (schemaBuilder) + +
+ +``` +عملية [جـدول: صنف] هذا.مهيكل: مـهيكل[جـدول]؛ +``` + +
+ +``` +handler [Model: type] this.schemaBuilder: SchemaBuilder[Model]; +``` + +يستعمل لإعادة مهيكل بناء على المعلومات في هذا الصنف. ### الدالة هات_اعتماديات_البناء (getBuildDependencies) @@ -1254,11 +2008,8 @@ func getBuildDependencies(): Array[String]; * `أخـطاء._التصال_مفقود_` (`Errors.CONNECTION_MISSING`): تُرجع عند استدعاء دالتي الحفظ أو الحذف على متغير من صنف جدول (model) لكن ذلك المتغير غير مرتبط بكائن `قـاعدة_بيانات`، أي أنه لم يُحمل مسبقًا من قاعدة البيانات. ---- - ## الرخصة حقوق النشر © 2026 سرمد خالد عبد الله هذا المشروع مرخص بموجب رخصة غنو العمومية الصغرى الإصدار 3.0 (LGPL-3.0). راجع ملفات `COPYING` و `COPYING.LESSER` للحصول على التفاصيل. - diff --git a/README.md b/README.md index 89d4be0..124cabe 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Rows + [[عربي]](README.ar.md) An ORM (object relational mapping) library for Alusus. @@ -11,7 +12,6 @@ We can install this library using the following statements: import "Apm"; Apm.importPackage("Alusus/Rows@0.4", { "Rows.alusus", "" }); ``` - A driver name must be included in the second argument, unless if you are implementing your own DB driver. The driver lets you connect with a specific DB type. Rows does not automatically load all drivers because these drivers have system dependencies and including all drivers automatically @@ -261,7 +261,7 @@ this the user needs to make the following additions to the classes: * Add DB type modifiers to the variables. * Add modifiers related to indexing, default values, and required fields, if needed. -Example +Example : ``` @model["cars", 1] @@ -334,17 +334,47 @@ class ConnectionParams { } ``` -This class contains the required information to connect to the database +This class contains the required information to connect to the database. + +#### dbName + +``` +def dbName: String = ""; +``` -`dbName` the name of the database we want to connect to it. +The name of the database to connect to. -`userName` the username for our account in the database. +#### userName -`password` the password of our account in the database +``` +def userName: String = ""; +``` -`host` the host address that run the database. +The username for the database account. -`port` the port on the host that we can access database through it. +#### password + +``` +def password: String = ""; +``` + +The password for the database account. + +#### host + +``` +def host: String = ""; +``` + +The host address running the database. + +#### port + +``` +def port: int = 0; +``` + +The port on the host to access the database through. ### CreateTable class @@ -360,15 +390,45 @@ class CreateTable { This class is used to create a model with a given information. -`name` the model name. +#### name -`notExists` specify if we need to create the model only of its not already exist. +``` +handler this.name = String; +``` -`columns` a map between column name and its information. +The model name. -`primaryKey` the primary key of the model. +#### notExists -`foreignKeys` the foreign keys of the model. +``` +handler this.notExists = Bool; +``` + +Specify if the model should only be created if it doesn't already exist. + +#### columns + +``` +handler this.columns = Map[String, SrdRef[Column]]; +``` + +A map between column name and its information. + +#### primaryKey + +``` +handler this.primaryKey = Array[String]; +``` + +The primary key of the model. + +#### foreignKeys + +``` +handler this.foreignKeys = Array[SrdRef[ForeignKey]]; +``` + +The foreign keys of the model. ### Delete class @@ -381,9 +441,20 @@ class Delete { This class is used to delete rows from a model based on a condition. -`table` the model name. +#### table + +``` +handler this.table = String; +``` +The model name. -`condition` the condition the a row must satisfy in order to delete it. +#### condition + +``` +handler this.condition(statement: CharsPtr, args: ...any); +``` + +The condition a row must satisfy in order to delete it. ### Value class @@ -418,12 +489,28 @@ class Insert { This class is used to insert a row to the model. -`table` the model name. +#### table + +``` +handler this.table = String; +``` + +The model name. + +#### data + +``` +handler this.data = Array[Value]; +``` -`data` the values of the row we want to add. +The values of the row to add. -`columns` the names of the columns that corresponds to the values. +#### columns +``` +handler this.columns = Array[String]; +``` +The names of the columns that correspond to the values. ### Select class @@ -438,13 +525,37 @@ class Select { This class is used to retrieve rows from the model. -`table` the model name. +#### table + +``` +handler this.table = Array[String]; +``` + +The model name. -`columns` the names of the columns we want to retrieve. +#### fields -`condition` the condition the a row must satisfy in order to select it. +``` +handler this.fields = Array[String]; +``` -`orderBy` the order of the selected rows. +The names of the columns to retrieve. + +#### condition + +``` +handler this.condition(statement: CharsPtr, args: ...any); +``` + +The condition a row must satisfy in order to select it. + +#### orderBy + +``` +handler this.orderBy = Array[String]; +``` + +The order of the selected rows. ### Update class @@ -459,13 +570,37 @@ class Update { This class is used to update a row, or a set of rows in a model. -`table` the model name. +#### table + +``` +handler this.table = String; +``` + +The model name. -`data` the new values of the columns +#### data -`columns` the columns we want to update its values. +``` +handler this.data = Array[Value]; +``` + +The new values of the columns. + +#### columns + +``` +handler this.columns = Array[String]; +``` -`condition` the condition the a row must satisfy in order to update it. +The columns to update their values. + +#### condition + +``` +handler this.condition(statement: CharsPtr, args: ...any); +``` + +The condition a row must satisfy in order to update it. ### Column class @@ -481,15 +616,45 @@ class Column { This class holds the column information. -`dataType` the type of data we want to store in the column. +#### dataType + +``` +handler this.dataType = SrdRef[DataType]; +``` + +The type of data to store in the column. + +#### notNull + +``` +handler this.notNull = Bool; +``` + +Specify if this column value is required, or it can be null. -`notNull` specify if this column value is required, or it can be null. +#### unique -`unique` specify if this column values are unique or not. +``` +handler this.unique = Bool; +``` + +Specify if this column values are unique or not. + +#### default + +``` +handler this.default = String; +``` -`default` the default value for this column when no value is provided. +The default value for this column when no value is provided. -`check` the check to apply on the value before insert it. +#### check + +``` +handler this.check(statement: CharsPtr, args: ...any); +``` + +The check to apply on the value before inserting it. ### Query class @@ -504,44 +669,73 @@ class Query [Model: type] { } ``` -`order` specify the order of the query. +This class is used to combine the clauses of an operation before execution. Usually the user does +not need to instantiate this manually; instead, it's instantiated through the `Db.from` method. -`where` a macro to set the condition of the query. +For example: -parameters: +``` +db.from[User].where[name == arg1].update[address = arg2]; +``` -* `this` a pointer to a Query object. -* `condition` the condition we want to set. +#### order -`update` a macro to apply an update query on the model. +``` +handler [exp: ast] this.order: ref[this_type] +``` -parameters: +Specify the order of the query. -* `this` a pointer to a Query object. -* `expression` the update expression. +#### where -`select` used to retrieve rows from a model. +``` +@member macro where [this, condition] +``` -`save` used to save a row in the model. +A macro to set the condition of the query. -parameters: +* `this`: A pointer to a Query object. +* `condition`: The condition to set. -* `model` a reference to the model we want to save the row to it. +#### update -`delete` used to delete from the model. +``` +@member macro update [this, expression] +``` -parameters: +A macro to apply an update query on the model. -* `model` a reference to the model we want to delete the row from it. +* `this`: A pointer to a Query object. +* `expression`: The update expression. -This class is used to combine the clauses of an operation before execution. Usually the user does -not need to instantiate this manually; instead, it's instantiated through the `Db.from` method. -For example: +#### select ``` -db.from[User].where[name = arg1].update[address = arg2]; +handler this.select(): Possible[Array[SrdRef[Model]]] ``` +Used to retrieve rows from a model. + +#### save + +``` +handler this.save(model: ref[Model]): Possible[Int] +``` + +Used to save a row in the model. + +* `model`: A reference to the model to save the row to. + +#### delete + +``` +handler this.delete(model: ref[Model]): Possible[Int] +``` + +Used to delete from the model. + +* `model`: A reference to the model to delete the row from. + #### Partial Matching (LIKE) To perform a partial match (equivalent to SQL's `LIKE` clause), use the `::` operator in the @@ -576,7 +770,13 @@ a model class or a comma separated list of all model classes constituting the DB will take care of building the database from the schema, or migrating it to the latest version by determining what migration functions are needed and running them. -`migrate` Migrates the DB to the current version, or builds it from scratch if it doesn't exist. +#### migrate + +``` +handler this.migrate(): SrdRef[Error] +``` + +Migrates the DB to the current version, or builds it from scratch if it doesn't exist. When a table is not found in the DB, SchemaBuilder will generate that table from the model definition. When the table already exists, it looks at the version of the model defined in @@ -591,32 +791,20 @@ functions have the following signature: ``` The upper migrator migrates from version 1 to version 2. You can also specify dependencies -in those migrations to make sure they are run in a specific order. For example: +in those migrations to make sure they are run in a specific order. + +For example: ``` @migration[1, 2, { User: 3 }] function migrateFromV1ToV2(db: ref[Db]): SrdRef[Error]; ``` -The upper example tells `SchemaBuilder` to run this migration when the `User` model is -at version 3. This makes sure that this migration is delayed until User is migrated to -version 3, and it also makes sure any migration that migrates User from version 3 is -delayed until this migration is executed. If multiple migrations are needed on a single -table before it reaches the latest version then `SchemaBuilder` will make sure to run -all those migrations, and run them in the correct order. - -If a model defines a migration that migrates from version 0, then `SchemaBuilder` will -not generate the table automatically from the model if the table doesn't exist and will -instead depend on running the migration, effectively allowing the user to create the -table manually on a new database instead of depending on the default table creator. +The upper example tells `SchemaBuilder` to run this migration when the `User` model is at version 3. This makes sure that this migration is delayed until User is migrated to version 3, and it also makes sure any migration that migrates User from version 3 is delayed until this migration is executed. If multiple migrations are needed on a singletable before it reaches the latest version then `SchemaBuilder` will make sure to run all those migrations, and run them in the correct order. +If a model defines a migration that migrates from version 0, then `SchemaBuilder` will not generate the table automatically from the model if the table doesn't exist and will instead depend on running the migration, effectively allowing the user to create the table manually on a new database instead of depending on the default table creator. ### Driver class -This is the base class for all DB drivers, which are responsible for all communication -with the database. It has many abstract methods used by `Db` class and the user mostly -won't need to deal with any of the methods of this class other than connection related -methods. - ``` class Driver { handler this.connect(parmas: ref[ConnectionParams]): Bool as_ptr; @@ -628,6 +816,56 @@ class Driver { } ``` +This is the base class for all DB drivers, which are responsible for all communication with the database. It has many abstract methods used by `Db` class and the user mostly won't need to deal with any of the methods of this class other than connection related methods. + +#### connect + +``` +handler this.connect(parmas: ref[ConnectionParams]): Bool as_ptr +``` + +Connect to the database. + +#### disconnect + +``` +handler this.disconnect() as_ptr +``` + +Disconnect from the database. + +#### isConnected + +``` +handler this.isConnected(): Bool as_ptr +``` + +Check if connected to the database. + +#### isConnectionEstablished + +``` +handler this.isConnectionEstablished(): Bool as_ptr +``` + +Check if the connection has been established. + +#### getConnectionParams + +``` +handler this.getConnectionParams(): ConnectionParams as_ptr +``` + +Get the connection parameters. + +#### getLastError + +``` +handler this.getLastError(): String as_ptr +``` + +Get the last error message. + ### Db class ``` @@ -657,94 +895,159 @@ class Db { This class is used to manage the access to the database and executing many queries on it. -`logging` when set to true the library will print the executed SQL statements to the console. +#### logging + +``` +db.logging: Bool +``` + +When set to true the library will print the executed SQL statements to the console. + +#### reconnectionDelay + +``` +db.reconnectionDelay: Word +``` + +The delay in microseconds that the library will wait after the connection to the server is lost before trying to reconnect. + +#### reconnectionAttemptCount + +``` +db.reconnectionAttemptCount: Int +``` + +The max number of reconnection retries before the library gives up and returns an error. + +#### ~init + +``` +handler this~init(d: SrdRef[Driver]) +handler this~init(initializer: closure(ref[SrdRef[Driver]])) +``` + +Initialize the database with the given driver. The closure version is used for supporting multi-threading, i.e. using the same `Db` object from multiple threads. The closure will be used to initialize a new driver for each new thread that uses the `Db` object. + +#### init + +``` +handler this.init(d: SrdRef[Driver]) +handler this.init(initializer: closure(ref[SrdRef[Driver]])) +``` +Initialize the database with the given driver. The closure version is used for supporting multi-threading. + +#### isConnected + +``` +handler this.isConnected(): Bool +``` + +Check if there is a connection with the database. + +#### getLastError + +``` +handler this.getLastError(): String +``` + +Get the last error. + +#### exec + +``` +handler this.exec(select: ref[Select]): Possible[Array[Array[String]]] +handler this.exec(update: ref[Update]): Possible[Int] +handler this.exec(insert: ref[Insert]): Possible[Int] +handler this.exec(delete: ref[Delete]): Possible[Int] +handler this.exec(createTable: ref[CreateTable]): Possible[Int] +handler this.exec(statement: CharsPtr, args: ...any): Possible[Int] +``` + +Execute a query. There is an overload for each type of query in addition to an overload for executing raw SQL statements. The version for raw SQL splits the SQL structure from the data, which are passed as extra args similar to printf. For write queries (insert, update, delete) returns the number of affected rows. The following data param types are supported: -`reconnectionDelay` the delay in microseconds that the library will wait after the connection -to the server is lost before trying to reconnect. +* `%n`: `CharsPtr` +* `%s`: `String` +* `%p`: `CharsPtr` +* `%i`: `Int` +* `%l`: `Int[64]` +* `%f`: `Float` +* `%d`: `Float[64]` +* `%as`: `Array[String]` +* `%ap`: `Array[CharsPtr]` +* `%ai`: `Array[Int]` +* `%al`: `Array[Int[64]]` +* `%af`: `Array[Float]` +* `%ad`: `Array[Float[64]]` -`reconnectionAttemptCount` The max number of reconnection retries before the library gives up -and returns an error. +#### execSelect -`init` used to initialize the database with the given driver. The closure version of the `init` -function and constructor are used for supporting multi-threading, i.e. using the same `Db` object -from multiple threads. The closure will be used to initialize a new driver for each new thread -that uses the `Db` object. +``` +handler this.execSelect(statement: CharsPtr, args: ...any): Possible[Array[Array[Nullable[String]]]] +``` -`isConnected` used to check if there is a connection with the database. +Similar to the raw SQL `exec` overload, except used for SQL statements that fetch data. + +#### from + +``` +handler [Model: type] this.from: Query[Model] +``` -`getLastError` used to get the last error. +Return a query based on the information of this class. -`exec` used to execute a query. There is an overload from this function for each type of queries in -addition to an overload for executing raw SQL statements. The version for raw SQL splits the SQL -structure from the data, which are passed as extra args to the function similar to printf. The -following types of data params are supported by this function: -* CharsPtr for field or table name: %n -* String: %s -* CharsPtr: %p -* Int: %i -* Int[64]: %l -* Float: %f -* Float[64]: %d -* Array[String]: %as -* Array[CharsPtr]: %ap -* Array[Int]: %ai -* Array[Int[64]]: %al -* Array[Float]: %af -* Array[Float[64]]: %ad +#### save -`execSelect` is similar to the `exec` version that uses raw SQL statement, except that it's used -for SQL statements that fetches data. +``` +handler [Model: type] this.save(model: ref[Model]) +``` -For write queries (inset, update, delete) the `exec` function returns the number od affected rows. +Call the method `save` in the class `Query`. -`from` used to return a query based on the information of this class. +#### schemaBuilder -`save` used to call the method `save` in the class `Query`. +``` +handler [Model: type] this.schemaBuilder: SchemaBuilder[Model] +``` -`schemaBuilder` used to return a schemaBuilder based on the information of this class. +Return a schemaBuilder based on the information of this class. -### getBuildDependencies Function +### getBuildDependencies ``` -func getBuildDependencies(): Array[String]; +func getBuildDependencies(): Array[String] ``` -Each of the available DB drivers defines this function for getting the external build dependencies -needed to build an executable that connects with the given database type. +Each of the available DB drivers defines this function for getting the external build dependencies needed to build an executable that connects with the given database type. ### Errors The `Errors` submodule contains error codes for all errors that can be returned by this library. * `Errors.DB_NOT_INITIALIZED`: Raised when the `Db` class is being used before being initialized. -* `Errors.DB_NOT_CONNECTED`: Raised when the `Db` is initialized with a DB driver but the driver is not properly - connected. +* `Errors.DB_NOT_CONNECTED`: Raised when the `Db` is initialized with a DB driver but the driver is not properly connected. * `Errors.SQL_ERROR`: Raised when an error occurs during the execution of an SQL statement. -* `Errors.CONNECTION_MISSING`: Raised when `save` or `delete` is called on a model that isn't connected to a `Db` - object, i.e. it wasn't previously loaded using a `Db` object. +* `Errors.CONNECTION_MISSING`: Raised when `save` or `delete` is called on a model that isn't connected to a `Db` object, i.e. it wasn't previously loaded using a `Db` object. ## To Do -- [ ] Add remaining DB operations: - - [ ] Adding column. - - [ ] Removing colum. - - [ ] Renaming column. - - [ ] Changing column type. - - [ ] Adding index. - - [ ] Removing index. - - [ ] Removing table. - - [ ] DB migrations. -- [ ] Add support for relational operations: - - [ ] Includes (eager loading). - - [ ] Loading related records. - - [ ] Associating and unassociating records. -- [ ] Add support for async operations. -- [ ] Add support for error codes for DB errors. - ---- + +* [ ] Add remaining DB operations: + * [ ] Adding column. + * [ ] Removing colum. + * [ ] Renaming column. + * [ ] Changing column type. + * [ ] Adding index. + * [ ] Removing index. + * [ ] Removing table. + * [ ] DB migrations. +* [ ] Add support for relational operations: + * [ ] Includes (eager loading). + * [ ] Loading related records. + * [ ] Associating and unassociating records. +* [ ] Add support for async operations. +* [ ] Add support for error codes for DB errors. ## License Copyright (C) 2026 Sarmad Abdullah -This project is licensed under the GNU Lesser General Public License v3.0 (LGPL-3.0). See the `COPYING` and `COPYING.LESSER` files for details. - +This project is licensed under the GNU Lesser General Public License v3.0 (LGPL-3.0). See the `COPYING` and `COPYING.LESSER` files for details. \ No newline at end of file