Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RawSql to BaseConnection->escape() #6332

Merged
merged 11 commits into from
Aug 25, 2022
Merged

Conversation

sclubricants
Copy link
Member

@sclubricants sclubricants commented Aug 2, 2022

This PR adds RawSql type to BaseConnection->escape(). It does not escape the RawSql.

This allows passing SQL functions in columns used for DML operations.

For instance you could pass CURRENT_TIMESTAMP() to a date time field instead of a literal value.

You could call your own SQL function as well.

Another is to pass SQL constants like DEFAULT in order to fill a column with default values.

<?php

    $data = [
        'id'          => new RawSql('DEFAULT'),
        'title'       => 'My title',
        'name'        => 'My Name',
        'date'        => '2022-01-01',
        'last_update' => new RawSql('CURRENT_TIMESTAMP()'),
    ];

    $builder->insert($data);
    /* Produces:
        INSERT INTO mytable (id, title, name, date, last_update)
        VALUES (DEFAULT, 'My title', 'My name', '2022-01-01', CURRENT_TIMESTAMP())
    */

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@kenjis kenjis added 4.3 enhancement PRs that improve existing functionalities labels Aug 2, 2022
@MGatner
Copy link
Member

MGatner commented Aug 3, 2022

Looks like a cool feature! The changes look good to me but I'd rather someone with a better idea of the larger database implications handle reviews. @iRedds or @paulbalandan ?

@kenjis
Copy link
Member

kenjis commented Aug 4, 2022

Please update the all notes in query_builder.rst:

.. note:: All values are escaped automatically producing safer queries.

@MGatner
Copy link
Member

MGatner commented Aug 4, 2022

Looking good! Thanks for all the reviews.

@sclubricants
Copy link
Member Author

.. note:: All values are escaped automatically producing safer queries.

@kenjis What do you propose we do here?

How about:

.. note:: All values except ``RawSql`` are escaped automatically producing safer queries.

@kenjis
Copy link
Member

kenjis commented Aug 4, 2022

I think the following section is weird. Because it explains escape(), but it explains about not escaping a lot.

Screenshot 2022-08-05 7 56 17

I think we should remove the sample and description for RawSql here.
Because it is not needed here.

This section explains how to use escape() and its behavior.
Devs never writes or should not write code like $db->escape(new RawSql('...')).
It does not make sense.

See the first sample code. The assumption here is that SQL statements are generated by concatenating strings.
Devs can write SQL functions and constants as they like in a string.
But the sentence "This allows you to call SQL functions and constants" is an explanation when we use QueryBuilder.

@kenjis
Copy link
Member

kenjis commented Aug 4, 2022

.. note:: All values except RawSql are escaped automatically producing safer queries.

Good. And can you add the following warning, too?

Screenshot 2022-08-05 8 16 12

@sclubricants
Copy link
Member Author

So you want to remove everything? Then none will know about its availability for use.

I think the example is good because it explains what the method does. The method does different things to different types of data. It could be possible to add other data types such as Datetime.

Its important to know how these datatypes are treated.

@sclubricants
Copy link
Member Author

Developers might should understand that the escape method is what they are relying on when they employ functions like insert. They might not write the actual code for db->escape() but they are none the less calling it via ignoring the escape parameter on functions like insert().

@kenjis
Copy link
Member

kenjis commented Aug 5, 2022

So you want to remove everything?

I thought again, and yes. Because the page explains how to use $db->query() (and simpleQuery()).
So RawSql is not needed for them.

Your explanation about RawSql and escape() is good, but it should not in the place.

Developers might should understand that the escape method is what they are relying on when they employ functions like insert. They might not write the actual code for db->escape() but they are none the less calling it via ignoring the escape parameter on functions like insert().

Yes, and the explanation should be in the insert() page. It is a QueryBuilder method.

@sclubricants
Copy link
Member Author

Maybe RawSql needs its own page

@sclubricants
Copy link
Member Author

I wonder if this will conflict with binds..

@MGatner
Copy link
Member

MGatner commented Aug 5, 2022

I wonder if this will conflict with binds..

Sounds like a test case is in order 😊

@sclubricants
Copy link
Member Author

No conflict with binds but did have to fix objectToArray() in BaseBuilder

@kenjis
Copy link
Member

kenjis commented Aug 6, 2022

No conflict with binds but did have to fix objectToArray() in BaseBuilder

Why doesn't the existing test fail?
Is a test case missing?

@sclubricants
Copy link
Member Author

The existing test just tests escape(). Ill write some tests to test things like insert().

@sclubricants
Copy link
Member Author

sclubricants commented Aug 8, 2022

Added RawSql test.. to test custom SQL function:

SELECT setDateTime('2022-06-01')

Returns: 2022-06-01 01:01:11

This way the RawSql has quotes in it to test and make sure quotes aren't being escaped.

@sclubricants sclubricants requested a review from kenjis August 8, 2022 21:44
Copy link
Member

@MGatner MGatner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kenjis last call?

@kenjis kenjis added the stale Pull requests with conflicts label Aug 22, 2022
@kenjis
Copy link
Member

kenjis commented Aug 22, 2022

Sorry, can you rebase to resolve the conflict?

@sclubricants sclubricants removed the stale Pull requests with conflicts label Aug 23, 2022
@iRedds
Copy link
Collaborator

iRedds commented Aug 23, 2022

The usage example is rather ambiguous.
It can be replaced with.

$data = [
    'title'       => 'My title',
    'name'        => 'My Name',
    'date'        => '2022-01-01',
];

$builder->set([
    'id'          => 'DEFAULT',
    'last_update' => 'CURRENT_TIMESTAMP()',
], null, false)->insert($data);

@sclubricants
Copy link
Member Author

The usage example is rather ambiguous.
It can be replaced with.

Your trick won't work on insertBatch()

@kenjis
Copy link
Member

kenjis commented Aug 24, 2022

@iRedds To be honest, I would like to throw an Exception to such code. It is difficult to read.

By the way, what do you mean ambiguous ?
It seems to me the sample code is easy to read and understand.

@MGatner
Copy link
Member

MGatner commented Aug 24, 2022

I think @iRedds was pointing out that we can already accomplish the same thing with other tools. insertBatch() is a good counter-example. I also assume this is the only way to use a Model to insert non-escaped data?

@kenjis
Copy link
Member

kenjis commented Aug 25, 2022

I agree that we can already accomplish the same thing with other tools.
But I think the sample code is okay even if there is another way to do the same thing.

@kenjis kenjis merged commit 6344fc7 into codeigniter4:4.3 Aug 25, 2022
@MGatner
Copy link
Member

MGatner commented Aug 25, 2022

Thanks all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.3 enhancement PRs that improve existing functionalities
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants