مسابقه حضوری ۳ آذر حذف شده و این مسابقه تعیینکنندهی رتبه و جایزهی شما است. اطلاعات بیشتر را میتوانید در اینجا کسب کنید.
لینکهای مفید برای شرکت در مسابقه:
در طول مسابقه، میتوانید سؤالات خود را از قسمت «سؤال بپرسید» مطرح کنید.
علی بهتازگی با کتابخانهی GORM که یک ORM به زبان Go است آشنا شده. او داکیومنت این کتابخانه را مطالعه کرده و به مرور زمان در حال پی بردن به امکانات جذاب این کتابخانه است. از آنجایی که علی فرد کنجکاوی است، او تصمیم گرفته تا سورس کد این کتابخانه را مطالعه کند و دریابد که این کتابخانه چگونه کار میکند. از آنجایی که کد این کتابخانه بسیار طولانی است و علی حوصلهی خواندن آن را ندارد. به دنبال نسخهی سادهای از یک ORM مشابه GORM میگردد تا بتواند با خواندن سورس کد آن، نحوهی کارکرد آن را متوجه شود. از شما میخواهیم تا چنین کتابخانهای را برای علی پیادهسازی کنید.
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
EntityConfigurator
🔗این استراکت در فایل configurators.go
تعریف شده است. موجودیتهای برنامه میتوانند شامل اطلاعات مختفی نظیر نام جدول باشند. این اطلاعات میتوانند در این استراکت ذخیره شوند. متدی با نام Table
برای این نوع داده تعریف شده است که فیلد table
(نام جدول) مربوط به موجودیت را مقداردهی میکند. در صورت نیاز، میتوانید ساختار این استراکت را تغییر دهید، اما نباید امضای متد Table
را تغییر دهید.
Driver
🔗قرار است ORM ما بتواند به دیتابیسهای مختلف متصل شود. درایورها، جزئیات پیادهسازی مربوط به DBMS های مختلف را مشخص میکنند. استراکت Driver
در فایل driver.go
تعریف شده است. همچنین یک استراکت بدون نام در متغیر Drivers
تعریف شده که شامل دو درایور در قالب فیلدهای PostgreSQL
و SQLite3
است. نام درایور PostgreSQL
را برابر با postgres
و نام درایور SQLite3
را برابر با sqlite3
قرار دهید. یک فیلد با نام PlaceHolderGenerator
نیز وجود دارد که مقدار آن یک تابع است که با دریافت تعداد پارامترهای موجود در یک کوئری SQL ، آرایهای از رشتهها که بیانگر placeholder مقادیر موجود در کوئری هستند را برمیگرداند. این تابع را برای دو درایور تعریفشده بهصورت زیر پیادهسازی کنید:
PostgreSQL
، تابع PlaceHolderGenerator
باید با دریافت n
، مجموعهای از رشتهها به فرم $i
(بهطوری که i
از 1
تا n
است) را برگرداند. برای مثال، اگر مقدار n
برابر با 3
باشد، خروجی باید بهترتیب شامل رشتههای $1
، $2
و $3
باشد.SQLite3
، تابع PlaceHolderGenerator
باید با دریافت n
، یک آرایه از رشتهها بهطول n
که مقادیر آن همگی برابر با ?
هستند برگرداند.Entity
🔗این اینترفیس در فایل orm.go
تعریف شده و شامل یک متد ConfigureEntity(e *EntityConfigurator)
است. موجودیتهای برنامه باید این اینترفیس را پیادهسازی کنند. متد ConfigureEntity
این اینترفیس، پیکربندی اولیهی یک Entity
را انجام میدهد (مثلاً نگهداری نام جدول مربوط به موجودیت) که به ازای هر Entity
توسط برنامهنویس آن پیادهسازی میشود.
ConnectionConfig
🔗این استراکت شامل پوینتری به یک sql.DB
، پوینتری به یک درایور و آرایهای از موجودیتهای برنامه است. از این ConnectionConfig
ها در تابع SetupConnections
استفاده میشود.
SetupConnections
🔗این تابع با دریافت تعداد نامشخصی ConnectionConfig
، اتصال مربوط به کانکشنها را برقرار میکند و مقداردهیهای اولیهی لازم برای کانکشنها را انجام میدهد.
Find
🔗این تابع با دریافت کلید اصلی (عددی) یک موجودیت از نوع T
(جنریک)، اطلاعات مربوط به سطر موردنظر از دیتابیس را باید در قالب یک آبجکت از نوع T
برگرداند. نام ستونها در جدول بهصورت snake_case
هستند، اما نام فیلدهای نوع دادهی T
بهصورت PascalCase
است. برای مثال، اگر در یک موجودیت، فیلدی با نام BodyText
داشته باشیم، در جدول متناظر با موجودیت، ستونی با نام body_text
وجود خواهد داشت. تضمین میشود که فیلدها برای ستونهای مختلف جدول تعریف شدهاند.
All
🔗این تابع، اطلاعات مربوط به سطرهای جدول موردنظر از دیتابیس (با توجه به نوع دادهی جنریک) را باید در قالب آرایهای از T
ها برگرداند.
First
🔗این تابع باید اطلاعات اولین سطر (بر اساس کلید اصلی جدول) در جدول موردنظر (با توجه به نوع دادهی جنریک) را در قالب آبجکتی از نوع T
برگرداند.
Last
🔗این تابع باید اطلاعات آخرین سطر (بر اساس کلید اصلی جدول) در جدول موردنظر (با توجه به نوع دادهی جنریک) را در قالب آبجکتی از نوع T
برگرداند.
QueryBuilder
🔗این استراکت شامل اطلاعات یک کوئری برای تبدیل به فرمت SQL است که در فایل query.go
تعریف شده. آن را به دلخواه پیادهسازی کنید.
تابع NewQueryBuilder
را بهگونهای پیادهسازی کنید که یک نمونهی جدید از نوع QueryBuilder
برگرداند.
متدهای زیر برای استراکت QueryBuilder
تعریف شده که باید آنها را پیادهسازی کنید:
Get
: این متد باید کوئری مدنظر (با توجه به متدهای فراخوانیشده روی QueryBuilder
) را اجرا کرده و نتیجه را در قالب یک آبجکت از نوع OUTPUT
(بهصورت جنریک) برگرداند. در اینصورت، تنها اولین نتیجه برمیگردد.All
: این متد باید کوئری مدنظر (با توجه به متدهای فراخوانیشده روی QueryBuilder
) را اجرا کرده و همهی نتایج را در قالب آرایهای از OUTPUT
ها (بهصورت جنریک) برگرداند.OrderBy
: این متد با دریافت نام یک ستون و نحوهی ترتیب (ASC
یا DESC
، بهمعنای صعودی یا نزولی) باید یک بخش ORDER BY
به کوئری اضافه کند.Where
: این متد میتواند حداقل دو آرگومان دریافت کند:AND
شود.=
) و سومین آرگومان مقدار مدنظر خواهد بود. شرط واردشده باید به کوئری اضافه شود. در صورتی که شرطی از قبل به کوئری اضافه شده باشد، شرط فعلی باید با شرطهای قبلی AND
شود.IN
باشد، آرگومان اول برابر با نام ستون موردنظر خواهد بود. آرگومان سوم به بعد، مقادیری هستند که مقدار ستون موردنظر باید حداقل برابر با یکی از آنها باشد.WhereIn
: عملکرد این متد، مشابه حالت سوم متد Where
است.AndWhere
: عملکرد این متد، مشابه متد Where
است.OrWhere
: عملکرد این متد، مشابه متد Where
است، با این تفاوت که اگر شرطی از قبل در کوئری موجود باشد، شرط جدید با شرطهای قبلی OR
خواهد شد.Limit
: این متد با دریافت یک عدد، limit موجود در کوئری را مشخص میکند.Offset
: این متد با دریافت یک عدد، offset موجود در کوئری را مشخص میکند.Table
: این متد با دریافت نام جدول در قالب یک رشته، نام جدولی که کوئری باید روی آن اجرا شود را مشخص میکند.GroupBy
: این متد با دریافت تعداد نامشخصی رشته، یک عبارت group by به کوئری اضافه میکند. در صورتی که این متد چند بار فراخوانی شود، ستونها باید بهترتیب به بخش group by کوئری اضافه شوند.Select
: این متد با دریافت تعداد نامشخصی رشته، مشخص میکند که مقدار کدام ستونها از جدول دیتابیس دریافت شوند. اگر این متد فراخوانی نشود، همهی ستونها (*
) باید از جدول موجود در دیتابیس دریافت شوند. اگر این متد چند بار فراخوانی شود، ستونها باید بهترتیب به کوئری اضافه شوند.SetDriver
: این متد با دریافت یک Driver
، باید موارد موردنیاز برای کوئری بیلدر (نظیر PlaceHolderGenerator
) را به موارد موجود در Driver
تغییر دهد.ToSql
: این متد باید کوئری SQL تولیدشده را در قالب یک رشته و مقادیر پارامترهای موجود در کوئری را در قالب آرایهای از interface{}
ها برگرداند. اگر اولین فراخوانی روی یک آبجکت جدید QueryBuilder
مربوط به متد ToSql
بود، مقدار خروجی error
را برابر با یک رشتهی غیر از خالی قرار دهید. در غیر اینصورت، error
را nil
برگردانید.نکته: در صورتی که چند شرط AND
و OR
شوند، صرفاً کافی است تا آنها را با استفاده از عملگرهای مربوطه (بین پرانتز) کنار یکدیگر قرار دهید. مثال:
کوئریهای تولیدشده توسط QueryBuilder
باید مطابق با مثالهای زیر باشند (فاصله و کوچکی و بزرگی حروف مهم است):
کوئری ایجادشده:
کوئری ایجادشده در درایور SQLite3:
کوئری ایجادشده در درایور PostgreSQL:
go.mod
و go.sum
را نیز در فایل زیپ ارسالی خود قرار دهید.پس از پیادهسازی برنامه، محتویات دایرکتوری اصلی برنامه را زیپ کرده و آپلود کنید، بهطوری که وقتی آن را باز میکنیم، با فایل driver.go
و سایر فایلهای برنامه مواجه شویم.