How to get last insert id when using sub query in Kohana - subquery

How do I return the correct $insert_id when using a sub query in Kohana?
I'm using the query method to return $insert_id and $affected_rows. It returns the correct value for $affected_rows but returns '1' for $insert_id which is incorrect.
Query below:
$sub = DB::select('id', 'username', 'email', 'lastVisitDate')->from('jos_users');
$qry_migrate_users = DB::insert('temp_users', array('old_id', 'username', 'email_work', 'last_login'))->select($sub);
list($insert_id, $affected_rows) = $qry_migrate_users->execute($this->conn_target);

MySQL returns only last insert id and affected rows. there is only one way to do what you want - execute your sub-select to array, and using foreach do single inserts. But it's a lilte bit slower operation! Or after inserting do something like that:
SELECT id FROM temp_users WHERE email IN (select email from jos_users)
You might understand the logic

Related

CQL query to return a boolean column based on a condition

Is it possible to retrieve a true/false answer from a CQL query that checks a condition -- for example, if a collection has a specific value?
Consider:
CREATE TABLE Test (Id text PRIMARY KEY, Roles set<text>)
INSERT INTO Test(Id, Roles)
VALUES ('123', {'Driver', 'Pilot', 'Janitor'})
I would like to get a true or false value depending on whether or not the set associated with Id='123' contains a specific value. Here is an imaginary syntax for what I'd like to get; it does not work:
SELECT
Roles CONTAINS 'Pilot' // <<== Not a valid syntax; this does not work
FROM Test
WHERE Id = '123'
Ok, here's what I came up with in the airport, quick...
Unfortunately, Cassandra CQL doesn't have a lot of the things that folks have grown accustomed to in SQL. For the problem of querying by id and roles CONTAINS 'Pilot', I came up with a similar solution.
CREATE TABLE roles (Id text, Roles set<text>);
CREATE INDEX on roles(roles);
Although, I used a secondary index to permit filtering on the roles collection.
The boolean is a little trickier. I created a user defined function (setting user_defined_functions_enabled: true in my cassandra.yaml).
Then the UDF:
CREATE OR REPLACE FUNCTION textToBoolean (input TEXT)
RETURNS NULL ON NULL INPUT RETURNS BOOLEAN
LANGUAGE java AS 'if (!input.equals("True")) { return false; }
return Boolean.valueOf(input);';
And then this works:
SELECT texttoboolean('True') AS success FROM roles WHERE id='123' AND roles CONTAINS 'Pilot';
success
---------
True
(1 rows)
All the UDF really does is let you return a boolean True if you really need to. So it returns true if it works, but returns nothing if it doesn't. Your solution of returning the COUNT might work better depending on what you're trying to accomplish.
It is possible to obtain a 1 or 0 result using COUNT:
SELECT COUNT(*)
FROM Test
WHERE Id = '123' AND Roles CONTAINS 'Pilot'
ALLOW FILTERING
You need ALLOW FILTERING to suppress a performance warning.

Getting index of the resultset

Is there a way to get the index of the results within an aql query?
Something like
FOR user IN Users sort user.age DESC RETURN {id:user._id, order:{index?}}
If you want to enumerate the result set and store these numbers in an attribute order, then this is possible with the following AQL query:
LET sorted_ids = (
FOR user IN Users
SORT user.age DESC
RETURN user._key
)
FOR i IN 0..LENGTH(sorted_ids)-1
UPDATE sorted_ids[i] WITH { order: i+1 } IN Users
RETURN NEW
A subquery is used to sort users by age and return an array of document keys. Then a loop over a numeric range from the first to the last index of the that array is used to iterate over its elements, which gives you the desired order value (minus 1) as variable i. The current array element is a document key, which is used to update the user document with an order attribute.
Above query can be useful for a one-off computation of an order attribute. If your data changes a lot, then it will quickly become stale however, and you may want to move this to the client-side.
For a related discussion see AQL: Counter / enumerator
If I understand your question correctly - and feel free to correct me, this is what you're looking for:
FOR user IN Users
SORT user.age DESC
RETURN {
id: user._id,
order: user._key
}
The _key is the primary key in ArangoDB.
If however, you're looking for example data entered (in chronological order) then you will have to have to set the key on your inserts and/or create a date / time object and filter using that.
Edit:
Upon doing some research, I believe this link might be of use to you for AI the keys: https://www.arangodb.com/2013/03/auto-increment-values-in-arangodb/

SQL injection ,why should you write 0 or 1=1

In SQL injection, why should you use 0 or 1=1, isn't this automatically evaluated as 1 in boolean operation? I don't understand why we should write it that way. Can someone explain?
Thanks in advance
Because it makes the condition always true.
For example, if someone's SQL code is:
string query = "SELECT * FROM Users WHERE Password = '" + somePassword + "'";
(Username clause omitted for brevity.)
Then you can enter something like this as the password:
' OR 1 = 1;--
Which would make the resulting query:
SELECT * FROM Users WHERE Password = '' OR 1 = 1;--'
The semicolon ends the statement, and -- denotes a comment so everything thereafter is ignored. So it simplifies to:
SELECT * FROM Users WHERE Password = '' OR 1 = 1
This will match all records in the table. Always. Because 1 = 1 is always true. Depending on how the application handles this response, you may be logged in. Perhaps even as the first user in the table, which is likely to be the admin user.
For SQL-injectable code, it's basically a universal password. (Provided you guess a correct username, which isn't difficult.)
Edit: I just noticed the 0 part of your question as well. This would be used when you expect the injected value to be looking for a number rather than a string. For example, consider a similar SQL statement:
string query = "SELECT * FROM Users WHERE Id = " + someID;
The leading 0 in the injected value prevents a syntax error. So the resulting query would be:
SELECT * FROM Users WHERE Id = 0 OR 1 = 1
Same concept as above. This will match all records every time.
Here is a brief explanation for this:-
select title, text from news where id=$id
In the example above the variable $id contains user-supplied data, while the remainder is the SQL static part supplied by the programmer; making the SQL statement dynamic.
Because the way it was constructed, the user can supply crafted input trying to make the original SQL statement execute further actions of the user's choice. The example below illustrates the user-supplied data β€œ10 or 1=1”, changing the logic of the SQL statement, modifying the WHERE clause adding a condition β€œor 1=1”.
select title, text from news where id=10 or 1=1
so the query will still get executed

Kohana Select order by

Sometimes when I refresh page the events I have sorts them DESCENDING by date, but I need ascending order by time.
http://prntscr.com/bubuz5
http://prntscr.com/bubvad
Code
public function get_frontpage_events()
{
return DB::select()->
from('events')->
where_open()->
where('frontpage', '=', 1)->
where('status', '=', 1)->
where('lang', '=', Session::instance()->get('lang'))->
where_close()->
order_by('date', 'ASC')->order_by('time', 'ASC')->
execute()->
as_array();
}
You query looks fine.
I don't know if you have a query log, but if you have you can check what query is executed, copy and paste it and run it yourself. The above code should create this SQL query (my guess is you are using MySQL):
SELECT * FROM `events` WHERE (`frontpage` = 1 AND `status` = 1 AND `lang` = 'EN') ORDER BY `date` ASC, `time` ASC
Do you do some other ordering/sorting in your view or your controller? When you loop over your results, are you sure you display all results?
The problem can be in order_by()->order_by() syntax. This method allows to use array in first argument, try this:
order_by(array('date','time'), 'ASC')

findAll validates input fields

I have problems with findAll(), it "fires" validation and that makes problems when I want to select/find a row by ID using LIKE... For example the query would look like this
SELECT * FROM table WHERE id LIKE '%345%'
In my model the id column is set to INTEGER so I get error message that says:
"%345%" is not a valid integer
Is there a way to skip the validation when I use findAll etc. or is it a bad idea, does the validation maybe prevent SQL injection?
You could form your where clause as follows
var id =345;
.findAll({where: ["id like ?", '%' + id + '%']});

Resources