If you want to modify the SELECT query just before Hibernate executes it, you can achieve this by leveraging a combination of Hibernate Interceptors
These allow you to intercept the SQL being generated and make modifications. |
Step 1: Create a Custom Interceptor
Create a class that extends org.hibernate.EmptyInterceptor. Override the onPrepareStatement method to intercept and modify the SQL query. |
Example: CustomSQLInterceptor.groovy
import org.hibernate.EmptyInterceptor class CustomSQLInterceptor extends EmptyInterceptor { @Override String onPrepareStatement(String sql) { // Modify the SQL query just before execution if (sql.toLowerCase().startsWith("select")) { // Example: Add a condition dynamically sql = sql.replace("WHERE", "WHERE 1=1 AND user_id = 100 AND") } return sql } } |
Step 2: Register the Interceptor
You need to register the interceptor with Hibernate. For Grails, you can configure it in application.groovy or use a Spring bean in resources.groovy. Option 1: Register in application.groovy Add the following Hibernate configuration in application.groovy: hibernate { interceptor = new CustomSQLInterceptor() } Option 2: Register in resources.groovy Alternatively, define the interceptor as a Spring bean in grails-app/conf/spring/resources.groovy: beans = { customSQLInterceptor(CustomSQLInterceptor) } Step 3: Test the Interceptor Run your Grails application and observe how the interceptor modifies the SQL queries. You can enable Hibernate SQL logging in application.groovy to verify: hibernate { format_sql = true use_sql_comments = true show_sql = true } Run a sample query and observe the logs to confirm that the SQL is being modified correctly. |
Wednesday, January 29, 2025
Grails on Groovy - Modify SQL Query Just Before Execute The Query Finally Run
Saturday, July 6, 2024
Bangladesh Railway - specification of seat category
এসি বার্থ (AC_B): এটি রেলওয়ের শীতাতপনিয়ন্ত্রিত কামরা। ‘তাপানুকূল স্লিপার’ বা ‘এসি কেবিন’ হিসেবেও পরিচিত। এসব কেবিনে দ্বিতল বিছানা থাকে। রাতের ডাবল কেবিনে চারজন যাত্রী শুয়ে যেতে পারেন আর সিঙ্গেল কেবিনে দুজন। |
এসি সিট (AC_S): আন্তনগর ট্রেনে রাতে যা ‘এসি বার্থ’, দিনে তা-ই হয়ে যায় ‘এসি সিট’। শীতাতপনিয়ন্ত্রিত এসব কেবিনের দ্বিতল বিছানা দিনের বেলায় হয়ে যায় বসার আসন। এ সময় ডাবল কেবিনে ছয়জন যাত্রী বসার ব্যবস্থা হয় আর সিঙ্গেল কেবিনে তিনজন। |
স্নিগ্ধা (SNIGDHA): ট্রেনের এসি কোচের চেয়ার সিট। দেশের সব আন্তনগর ট্রেনে না থাকলেও বেশির ভাগ জনপ্রিয় গন্তব্যের ট্রেনে স্নিগ্ধা কোচ থাকে। আরামদায়ক বসার আসনের ব্যবস্থা থাকায় এই কোচে ভ্রমণও হয় আরামদায়ক। |
এসি চেয়ার (AC_CHAIR): ‘তাপানুকূল এসি চেয়ার’ হিসেবেও পরিচিত। ট্রেনের কোচ বা বগির এই আসনগুলো কোনো কোনো ট্রেনে স্নিগ্ধা হিসেবেও পরিচিত। |
প্রথম শ্রেণি বার্থ (F_BERTH): প্রথম শ্রেণি বার্থ নন–এসি কেবিন হিসেবেও পরিচিত। এসব কেবিনে দ্বিতল বিছানা থাকে। রাতের ডাবল কেবিনে চারজন যাত্রী শুয়ে যেতে পারেন আর সিঙ্গেল কেবিনে দুজন। |
প্রথম শ্রেণি সিট (F_SEAT): সাধারণত শোয়ার বার্থ বা বিছানাওয়ালা কেবিনগুলো দিনের বেলায় প্রথম শ্রেণি সিট হিসেবে ব্যবহৃত হয়। এ সময় ডাবল কেবিনে ছয়জন যাত্রী বসার ব্যবস্থা হয় আর সিঙ্গেল কেবিনে তিনজন। |
প্রথম শ্রেণি চেয়ার (F_CHAIR): নন–এসি চেয়ার কোচের আসন। চেয়ারগুলো বেশ বড় ও আরামদায়ক। পা ছড়িয়ে বাসার মতো পর্যাপ্ত জায়গা থাকে। |
শোভন চেয়ার (S_CHAIR): দেশের প্রায় সব আন্তনগর ট্রেনে শোভন চেয়ার আছে। দ্বিতীয় শ্রেণির এই কামরা নন–এসি। স্নিগ্ধার কাছাকাছি মানের চেয়ার। তাই ভ্রমণ মোটামুটি আরামদায়ক। ভাড়াও প্রথম শ্রেণির চেয়ারের চেয়ে কম। |
শোভন (SHOVAN): ট্রেনের শোভন কোচে রেক্সিনে মোড়ানো মুখোমুখি আসন। অনেকটা বেঞ্চের মতো হলেও পেছনে হেলান দেওয়ার ব্যবস্থা থাকে। এই আসনে দুজনে বসতে হয়। মেইল ও কিছু আন্তনগর ট্রেনে শোভন আসন আছে। কম খরচের এসব আসন দীর্ঘ ভ্রমণের জন্য আরামদায়ক নয়। |
সুলভ (SHULOV): কাঠের বেঞ্চের মতো আসনে বসার ব্যবস্থা। এটি মেইল বা কমিউটার ট্রেনের দ্বিতীয় শ্রেণির আসন। |
Thursday, July 4, 2024
How To Read and Update Data From Google Sheets Using PHP
Create New Project on the Google Cloud Platform The first step to creating a new project to be able to access Google’s resources is to go to the Google Cloud Console https://console.cloud.google.com/ and New Project as below: Fill in the basic details that are asked on the form you get when you click New Project and submit it and you should be done. |
After create navigtate to project, like - https://console.cloud.google.com/welcome?project=project-spreadsheet-xxx In our case, since we plan to use the Google Sheets API, we will have to first enable the said API. To do that, check below screenshot click Enabled APIs & Services and then, from the top, click ENABLE APIS AND SERVICES. Or directly go to https://console.cloud.google.com/apis/library?project=project-spreadsheet-xxx to enable APIs you need. Find Google Sheets API and enable like below: |
Once enabled, we now have to create a credentials. For our case, we want to create a Service Account. Here, make sure you choose Owner as your role and then finally move ahead to create the service account. |
After the successful creation of the service account, you will be redirected to the list of credentials.
On that page, by clicking the Edit icons as shown below, you will be redirected to another page from where we can download the credentials as a JSON file.
Just follow along. Also, don’t forget to copy the email id that should be listed below the Service Accounts section.
Use this link https://console.cloud.google.com/iam-admin/settings to delete any existing project. Use this link https://console.cloud.google.com/cloud-resource-manager for all of your projects. |
Install the Google API Client Package
In order to interact with a google sheet using Composer, we will need to first bring in the Google API Client package.
Let’s do that by running the following command:
composer require google/apiclient |
ont forget to copy the email id that should be listed below the Service Accounts section. We will need this email id. So, go to your Google Cloud Console and from under Service Accounts, copy this email id. |
Now, let’s create a new Google sheet by going to docs.google.com and create a new spreadsheet. Then click the Share button on the top right of the newly created Google sheet and paste your service account email id here, to share the sheet with this email id (which is essentially your service account). like below |
Below is full PHP script to get Google Sheet data and update accordingly: |
<?php use Google\Client; use Google\Service\Drive; use Google\Service\Sheets; use Google\Service\Sheets\ValueRange; set_time_limit(60 * 60 * 12); ini_set("memory_limit", "-1"); ini_set('display_errors', 1); error_reporting(E_ALL); ini_set('display_startup_errors', 1); $client = new Client(); $client->setAuthConfig('creds.json'); $client->setScopes(['https://www.googleapis.com/auth/spreadsheets']); $client->useApplicationDefaultCredentials(); $service = new Sheets($client); $spreadsheetId = "1AN34n84blDoH_xxxxxxxxxx_faP6S5pjO5xaGdk7t77qPAgQY"; $ranges = 'Sheet1!A1:C20'; $params = array( 'ranges' => $ranges, 'majorDimension' => 'ROWS' ); //execute the request $result = $service->spreadsheets_values->batchGet($spreadsheetId, $params); if (!$result) { return [ 'error' => true, 'message' => 'missing row data' ]; } $values = $result->getValueRanges(); echo "<pre>"; print_r($values); echo "</pre>"; $updateRow = []; $updateRow[] = ["Name1", "Id1", "Group1-".time()]; $valueRange = new ValueRange(); $valueRange->setValues($updateRow); $range = 'Sheet1!A2:C'.(count($updateRow) + 1); // where the replacement will start, here, first column and second line $options = ['valueInputOption' => 'USER_ENTERED']; $service->spreadsheets_values->update($spreadsheetId, $range, $valueRange, $options); |
Respective Google Sheet is as below after update: |
Monday, June 24, 2024
Gram Chara Oi Ranga Matir Poth Lyrics
গ্রামছাড়া ওই রাঙা মাটির পথ
আমার মন ভুলায় রে।
ওরে কার পানে মন হাত বাড়িয়ে
লুটিয়ে যায় ধুলায় রে আমার
মন ভুলায় রে।
গ্রামছাড়া ওই রাঙা মাটির পথ
আমার মন ভুলায় রে।
ও যে আমায় ঘরের বাহির করে,
পায়ে-পায়ে ধরে
মরি হায় হায় রে ।
ও যে কেড়ে আমায় নিয়ে যায় রে
যায় রে কোন চুলায় রে আমার
মন ভুলায় রে।
ও কোন বাঁকে কী ধন দেখাবে,
কোনখানে কী দায় ঠেকাবে---
কোথায় গিয়ে শেষ মেলে যে
ভেবেই না কুলায় রে আমার
মন ভুলায় রে।
গ্রামছাড়া ওই রাঙা মাটির পথ
আমার মন ভুলায় রে
গ্রামছাড়া ওই রাঙা মাটির পথ
আমার মন ভুলায় রে ।।
Ami Tomari Premo Vikhari Lyrics
Ami Tomari Premo Vikhari Lyrics
Ore Nil Doriya Lyrics
Ore Nil Doriya Lyrics
ওরে নীল দরিয়া
আমায় দে রে দে ছাড়িয়া
বন্দি হইয়া মনোয়া পাখি হায় রে
কান্দে রইয়া রইয়া
ওরে নীল দরিয়া
আমায় দে রে দে ছাড়িয়া
বন্দি হইয়া মনোয়া পাখি হায় রে
কান্দে রইয়া রইয়া
ওরে নীল দরিয়া
কাছের মানুষ দূরে থুইয়া
মরি আমি ধরফড়াইয়া রে
দারুণ জ্বালা দিবানিশি
দারুণ জ্বালা দিবানিশি অন্তরে অন্তরে
আমার এত সাধের মন বঁধুয়া হায় রে
কী জানি কী করে
ওরে সাম্পানের নাইয়া
আমায় দে রে দে ভিড়াইয়া
বন্দি হইয়া মনোয়া পাখি হায় রে
কান্দে রইয়া রইয়া
ওরে সাম্পানের নাইয়া
হইয়া আমি দেশান্তরী
দেশ-বিদেশে ভিড়াই তরী রে
নোঙ্গর ফেলি ঘাটে ঘাটে
নোঙ্গর ফেলি ঘাটে ঘাটে বন্দরে বন্দরে
আমার মনের নোঙ্গর পইড়া আছে হায় রে
সারেং বাড়ির ঘরে
এই না পথ ধইরা
আমি কত যে গেছি চইলা
একলা ঘরে মন বঁধুয়া আমার
রইছে পন্থ চাইয়া
Writer(s): Alom Khan, Mukul Chudhury
Sunday, December 17, 2023
Using JavaScript to Upload Large Files in Chunks as Parts and Avoid Server Limits
We know that PHP config files has the limit to upload files to server, you know that uploading large files can be a real pain. You have to find the loaded php.ini file, edit the upload_max_filesize and post_max_size settings, and hope that you never have to change servers and do all of this over again. |
We will do some trick to upload very very large file to server without manipulate any configuration, does not matter how small the limit is. We actually will send files from browser chunk by chunk. Chunk can be as small as our demand. Suppose if our server accept max 1mb request limit, we will send 1mb per request and many more. |
This will include two parts (1) is to send files chunk by chunk from browser to server and the other part (2) is save file parts into single file. I will use PHP example at backend to save file into server. |
So below is Javascript parts with description: |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>File Upload Chunk</title> </head> <body> <div class="form"> <input type="file" id="file"/> <button type="button" id="upload">Upload</button> </div> <div class="toast"> <div id="toast"></div> </div> <script type="text/javascript"> document.getElementById("upload").addEventListener("click", () => { let files = document.getElementById("file").files; if (files.length === 0) { alert("File required"); } else { showToast("Uploading"); doUploadFileChunk(files[0], 1); } }); function doUploadFileChunk(file, chunk) { let chunkLimit = 1024 * 50; // Limit of file chunk send to server is 50 KB for test purpose // Blob from position let fromSlice = (chunk - 1) * chunkLimit; // Blob to position let nextSlice = fromSlice + chunkLimit - 1; // new FormData() let formData = new FormData(); formData.append("file_number", chunk); formData.append("file_name", file.name); formData.append("file_part", file.slice(fromSlice, nextSlice + 1)); // Processing small part of file console.log(`Sending from ${fromSlice} to ${nextSlice} KB`); // Sending to server let xhr = new XMLHttpRequest(); xhr.open("POST", "upload.php", true); xhr.setRequestHeader("Accept", "application/json"); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { console.log("Status = " + xhr.status); try { let response = JSON.parse(xhr.responseText); console.log(response); if (response.uploaded) { let percent = Math.floor((nextSlice / file.size) * 100); if (nextSlice < file.size) { showToast(`Uploading file - ${percent}% completed`); setTimeout(() => { doUploadFileChunk(file, chunk + 1); }, 200); } else { showToast(`Upload completed, processing started`); } } else { alert("Failed to upload file"); } } catch (e) { console.log("Complete = " + xhr.responseText); console.log(e); alert("Failed to upload file"); } } }; xhr.send(formData); } function showToast(text) { document.getElementById("toast").innerHTML = text; } </script> <style type="text/css"> div.form { padding: 20px; } div.toast { padding: 20px; background-color: green; color: white; font-size: 31px; } </style> </body> </html> |
And respective PHP file is as below: |
<?php $output = ["uploaded" => true, "file" => $_FILES["file_part"]]; $uploadFile = sprintf("storage/%s", $_POST['file_name']); if ($_POST["file_number"] == 1) { if (file_exists($uploadFile)) { unlink($uploadFile); } } $destination = fopen($uploadFile, "a+"); if (FALSE === $destination) die("Failed to open destination"); $handle = fopen($_FILES["file_part"]["tmp_name"], "rb"); if (FALSE === $handle) die("Failed to open blob"); $BUFFER_SIZE=1*1024*1024; // 1MB, bigger is faster while( !feof($handle) ) { fwrite($destination, fread($handle, $BUFFER_SIZE) ); } fclose($handle); fclose($destination); echo json_encode($output); |