accents added around mysql functions in codeiginter - codeigniter

i want to left join one table with three conditions.
like,
$this->db->select('c.*, s.salary_id', FALSE);
$this->db->from('clock_i_o c');
$this->db->join('salary s', 'c.cio_thrp_id = s.salary_thrp_id AND YEAR(c.cio_time) = s.salary_year AND WEEK(c.cio_time) = s.salary_week AND WEEK(c.cio_time) <> WEEK(NOW())', 'left');
problem is ci automatically adds accents to the mysql functions like YEAR, WEEK.
and query becomes like,
... LEFT JOIN `salary` `s` ON `c`.`cio_thrp_id` = `s`.`salary_thrp_id` AND `YEAR`(c.cio_time) = s.salary_year AND `WEEK`(c.cio_time) = s.salary_week AND `WEEK`(c.cio_time) <> WEEK(NOW())
i want to remove that accents. Thanks

According to the documentation there is a 4th Parameter
try this :
$this->db->join('salary s', 'c.cio_thrp_id = s.salary_thrp_id AND YEAR(c.cio_time) = s.salary_year AND WEEK(c.cio_time) = s.salary_week AND WEEK(c.cio_time) <> WEEK(NOW())', 'left', false);
Fore mor information take look #the documentation here

Related

Building LINQ Expression Getting Ignored

I'm trying to build a linq query coming from a table grid from the client side, so im expecting page offset, page start, order and the traditional paging parameters. I have the following code:
[Route("api/settings/logs")]
public Rest.DatatablesResponse GetLogs(int draw, int start, int length) {
var query_string = Request.GetQueryNameValuePairs().ToDictionary(x => x.Key, x => x.Value);
var search = query_string["search.value"];
int order_column = int.Parse(query_string["order[0].column"]);
var order_direction = query_string["order[0].dir"];
var count = db.Logs.Count(q => q.Mode == 2);
var logs = (from l in db.Logs
where l.Mode == 2
select new {
id = l.ID,
mode = l.Mode,
phase_id = l.Phase.ID,
created = l.Created,
user = l.User.Name,
blender_name = l.Blender.Name,
oil_name = l.Oil,
oil_quantity = l.OilQuantity,
production_cycle_name = l.ProductionCycle.Name
});
if (order_direction == "asc") {
if (order_column == 0) logs.OrderBy(q => q.created);
else if (order_column == 2) logs.OrderBy(q => q.production_cycle_name);
} else {
if (order_column == 0) logs.OrderByDescending(q => q.created);
else if (order_column == 2) logs.OrderByDescending(q => q.production_cycle_name);
};
if (!string.IsNullOrEmpty(search)) {
logs.Where(q => q.blender_name.Contains(search) ||
q.oil_name.Contains(search) ||
SqlFunctions.StringConvert((decimal)q.id).Contains(search));
}
logs.Skip(start).Take(length);
DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0,System.DateTimeKind.Utc);
var steps = from l in logs.ToList()
select new {
id = l.id,
message = StringHelpers.FormatWith(_tpl_message[l.phase_id.ToString() + l.mode.ToString() ], l) ,
created = dtDateTime.AddSeconds(l.created).ToString("h:mmtt - MMMM d, yyyy"),
production_cycle_name = l.production_cycle_name
};
return new Rest.DatatablesResponse {
draw = draw,
recordsTotal = count,
recordsFiltered = count,
data = steps.ToArray()
};
}
My problem is the skip and take and orderby expressions are getting ignored for some reason, and this is the SQL code generated just before converting my linq expressions to a list. From my understanding, the query should not be executed or evaluated until my logs.ToList() call, so the ordering and take/skip should be taken into account, but it's not:
{SELECT
[Extent1].[ID] AS [ID],
[Extent1].[Mode] AS [Mode],
[Extent1].[Phase_ID] AS [Phase_ID],
[Extent1].[Created] AS [Created],
[Extent2].[Name] AS [Name],
[Extent3].[Name] AS [Name1],
[Extent1].[Oil] AS [Oil],
[Extent1].[OilQuantity] AS [OilQuantity],
[Extent4].[Name] AS [Name2]
FROM [dbo].[Steps] AS [Extent1]
LEFT OUTER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[User_Id] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Blenders] AS [Extent3] ON [Extent1].[Blender_ID] = [Extent3].[ID]
LEFT OUTER JOIN [dbo].[ProductionCycles] AS [Extent4] ON [Extent1].[ProductionCycle_ID] = [Extent4].[ID]
WHERE 2 = [Extent1].[Mode]}
Irrelevant P.S. I'm using the not so clever ifs for building the order expression instead of using DynamicLINQ since i have only two sortable columns.
logs.Skip(start).Take(length);
Creates a IQueryable<T> where T is the same anonymous type of which logs is an IQueryable<T> but with start items skipped. Then from that it creates a similarly typed IQueryable<T> where lenght items are the most that will be taken.
Then it throws that away and lets it be garbage collected. (Or ideally the compiler or jitter steps will realise it's thrown away and cut out the whole thing).
Then logs.ToList() goes back to the logs you still have and creates a list from it.
You should replace the Skip and Take line with:
logs = logs.Skip(start).Take(length);
So that you are actually making use of this skipping and taking.
I'm using the not so clever ifs for building the order expression instead of using DynamicLINQ since i have only two sortable columns.
There's nothing particularly not-clever about that, except that you make the same mistake; apply the OrderBy and then throwing away the result instead of using it. Likewise with the Where. You need logs = logs.OrderBy(...) etc.
I'd also question from l in logs.ToList() select new {…} here.
It might be the best approach, if obtaining that list in one step has some advantage. However otherwise:
from l in logs select new {…}
Do the select work on the database, retrieving just what you need.
from l in logs.AsEnumerable() select new {…}
Do the select work in the application, appropriate if part of it cannot be converted to database work, but do it as it comes rather than loading it all into memory first.
from l in await logs.ToListAsync() select new {…}
Has the downside of ToList() but in asynchronous uses, then (assuming your provider has a ToListAsync() method) allows for awaiting.
ToList() is rarely the best option here.

why is this not possible in doctrine

I have to do some queries, while i was trying different ways, i found out that the next lines are not "recognized" by doctrine (it gives errors):
for example, when i want to compare if some data in the db is equal to a literal, here the condition:
('u.gender = M')
this is how my table look like:
id gender
1 M
2 M
3 F
it throws a semantical error. Also when comparing dates that way.
I would like to know why this is not recognized by doctrine, while comparing directly with numbers is accepted:
condition: ('u.age = 15')
First option you can do this way-
$M = 'M';
$age = 15;
$query = $this->createQueryBuilder('t')
->where('u.gender = :M AND u.age = :age')
->setParameters(array('M'=> $M,'age'=>$age);
another way to do this-
$query = $this->createQueryBuilder("t")
->where("u.gender = 'M' AND u.age = 15");
So i guess the answer to my question would be that it was not working because doctrine didn't recognize M as a string. That is why it was necessary to use inverted commas like #Mehedi said.
Another way of solving this was to use the query builder:
$v = 'M';
$condition = $this->qb->expr()->eq('u.gender', $this->qb->expr()->literal($v));
but i guess that is just long and hard to read. So the shortest thing would be just:
$condition = ("u.gender = 'M'");

Oracle Update with Joins

I'm trying to convert few MS Access Queries into Oracle. Following is one of the query from MS Access.
UPDATE [RESULT] INNER JOIN [MASTER]
ON ([RESULT].[LAST_NAME] = [MASTER].[LAST_NAME])
AND ([RESULT].[FIRST_NAME] = [MASTER].[FIRST_NAME])
AND ([RESULT].[DOCUMENT_NUMBER] = [MASTER].[DOCUMENT_NUMBER])
AND ([RESULT].[BATCH_ID] = [MASTER].[LEAD_ID])
SET [MASTER].[CLOSURE_REASON] = "Closed For Name and Document Number Match",
[MASTER].[RESULT_ID] = [RESULT].[ID],
[MASTER].[RESULT_PID] = [RESULT].[PID]
WHERE (([MASTER].[CLOSURE_REASON] Is Null)
AND ([MASTER].[REC_CODE] = "A1")
AND ([RESULT].[EVENT_DATE] = [MASTER].[EVENT_DATE])
AND ([RESULT].[EVENT_TYPE] = "Open")
AND ([MASTER].[DOCUMENT_NUMBER] Is Not Null)
AND ([MASTER].[DOCUMENT_NUMBER)] "null"));
First I received ORA-01779: cannot modify a column which maps to a non key-preserved table Error. I followed different examples (including MERGE) from your site and modified my original query. Now, I receive ORA-30926: unable to get a stable set of rows in the source tables Error.
Most of the examples showed only one join between the tables but I have to make more joins based on my requirements.
Any help translating this query in to Oracle would be Great. Thanks!
I believe this should be equivalent.
UPDATE master m
SET closure_reason = 'Closed For Name and Document Number Match',
(result_id, result_pid) = (SELECT r.id, r.pid
FROM result r
WHERE m.last_name = r.last_name
AND m.first_name = r.first_name
AND m.lead_id = r.batch_id
AND m.document_number = r.document_number
AND m.event_date = r.event_date
AND r.event_type = 'Open')
WHERE m.closure_reason IS NULL
AND m.rec_code = 'A1'
AND m.document_number IS NOT NULL
AND m.document_number != 'null'
AND EXISTS( SELECT 1
FROM result r
WHERE m.last_name = r.last_name
AND m.first_name = r.first_name
AND m.lead_id = r.batch_id
AND m.document_number = r.document_number
AND m.event_date = r.event_date
AND r.event_type = 'Open' )
Obviously, however, this isn't tested. If you could post the DDL to create your tables, the DML to insert a few rows, and show the expected result, we could test our code and would likely be able to give you more accurate answers.

Code igniter prepending db prefix in table aliases

I have configured code igniter to use db prefix.
At all other places it is working as expected but while creating table aliases it is prepending db prefix.
Code is as under:-
$this->db->from('table_a');
$this->db->join('table_b', 'table_a.id = table_b.a_id', 'left');
-----
$this->db->join('table_b as tablebAlias', 'table_c.id = tablebAlias.a_id', 'left');
Assuming my dbprefix is set to value 'foo'.
Final query which is getting executed is as under:-
Select * From foo_table_a left join foo_table_b on foo_table_a.id = foo_table_b.a_id
--- left join foo_table_b as tablebAlias on foo_table_c.id = foo_tablebAlias.a_id
Any help will be highly appreciable.
Thanks,
Jatin
I found out that manual queries ignore table prefix. I also found out that there is a way to add table prefix to manual queries:
In config/database.php
One can do this:
$db['default']['dbprefix'] = "feed_";
$db['default']['swap_pre'] = "{PRE}";
So that this can be done:
$sql = "SELECT * FROM {PRE}item";
$query = $this->db->query($sql);
The {PRE} becomes feed_.
But swap_pre is not config.php which leads me to think that this is CI 2.0 feature.

Add a clause to a MySQL statement without quotes using CodeIgniter's Active Record functions

I wanted to update a row using active records in codeigniter, and I only want to increment a field value (received_qty = received_qty +1) , I realized that I can do that in usual sql, but I cant in codeigniter active records
$update['received_qty'] = 'received_qty + 1';
$update['received_date'] = date("Y-m-d");
$this->db->where($where);
$this->db->update('vrs_distribution', $update);
anyone know how to do it using active records?
This will work.
$this->db->set('received_qty', 'received_qty + 1', FALSE);
$this->db->set('received_date', date("Y-m-d"));
$this->db->where($where);
$this->db->update('vrs_distribution');
ActiveRecord escapes everything put into a set(), where() and many other methods. Where and set can both take an optional third parameter of $escape which is a boolean. Set it to FALSE and CodeIgniter will not escape anything, meaning your field increment wont be treated as a string.
Or you can do:
$this->db->query('UPDATE vrs_distribution SET received_qty = received_qty + 1, received_date = CURDATE() WHERE id = ' . $id);
You would need to modify WHERE clause to suit you though
status set to zero(Update)
$this->db->set('IsCurrent', '0');
$this->db->where('AcademicYearID',$academicYearId);
$this->db->update('academicyear');
I was going to ask a similar question just a little bit different, but the problem was the same: I needed to update a date with an interval (expiry_date = expiry_date + interval 3 month) and Phil Sturgeon's answer did solve the problem.
However, what I realized is that you can still use the array for the fields that can have quotes, meaning that you could write:
$this->db->set('received_qty', 'received_qty + 1', FALSE);
$this->db->set('expired_date', 'CURDATE() + INTERVAL 10 DAY', FALSE); //extra example 1
$update['received_date'] = date("Y-m-d");
$update['receiver'] = $receiver_name; //extra example 2
$this->db->where($where);
$this->db->update('vrs_distribution', $update);
Where $this->db->last_query() would output:
UPDATE `vrs_distribution`
SET `received_qty` = received_qty + 1,
`expiry_date` = CURDATE() + INTERVAL 10 DAY, #extra example 1
`received_date` = '2015-07-01 16:00:00',
`receiver` = 'strike_noir', #extra example 2
WHERE #where clause with backticks
Notice that the fields where set() was used do not have quotes and appear in the first place. The rest of the query has backticks (letting "CodeIgniter protect the remaining fields").
You seem pretty close, there isn't an 'increment by one' command in CI's ActiveRecord (or in SQL for that matter).
$update['received_qty']++;
$update['received_date'] = date("Y-m-d");
$this->db->where($where);
$this->db->update('vrs_distribution', $update);

Resources