-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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 Upsert/UpsertBatch to builder #6294
Conversation
use styles and css classes fromm debug.css as it is in production.php
before this PR it shows: 404 - Page Not Found Page Not Found because $messages is always set (as I have seen) After PR: 404 Page Not Found
The duplicate code can be resolved by refactoring. The insertBatch() method can point to the new executeBatch() method. The setInsertBatch() method can point to the new setBatch() method. Also a small adjustment to _insertBatch() method will be to use the new getValues() method. I didn't want to change them yet so you guys could see what is going on here before the change. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- CI4 follows PSR-12 so you need to limit lines to 80 (120) characters (https://github.com/codeigniter4/CodeIgniter4/blob/develop/contributing/styleguide.md#lines).
- I recommend wrapping SQL code in tests in Nowdoc (or Heredoc). This will make it easier to read. It also seems to me that it is worth separating the SQL generation tests into separate methods for each driver.
- It is better to separate life tests and SQL generation tests, according to the same principle as it is now in the repository.
- Need tests for exceptions thrown in
batchExecute()
. - I think the _upsertBatch() method of the SQLite and Postgre drivers should throw an exception if the
$constraints
variable is empty. Otherwise, the method becomes a duplicate of insertBatch()
Very nice work on this feature, much easier to review after splitting apart. @iRedds gave a great review so I will refrain, but I'm here watching. |
e2f86a5
to
45e0e87
Compare
|
a52b4f8
to
d9ac9a7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the context of individual SQL code generation tests, see how the class is implemented https://github.com/codeigniter4/CodeIgniter4/blob/develop/tests/system/Database/Live/OCI8/LastInsertIDTest.php
SQL for Postgre and SQLite is the same. SQL for Oracle and MSSQL are similar for the most part. Therefore, it is possible to confuse what exactly caused the error.
I think we need to hear the opinion of the maintainers on this issue.
MySQL does not depend on indexes (constraint) in the same way as other DBMSs for upsert queries. Honestly, I don’t even know if it makes sense in other DBMSs to perform search operations for intexes with an empty $constraints variable.
You need to add a description to the documentation and changelog.
If the test "PHPUnit / PHP 8.1 - Postgre (pull_request)" fails the test then you know that the issue is with Postgre. Or if you are running locally whichever database assigned as "tests". The live/driver directory is for tests which have no counterpart in the other drivers. In this case the same call returns a value for all of them.
My original conception was to have all the DBMSs work in the same way as MySQL. However some of them don't allow using multiple constraints at one time. So I changed to pick up the first constraint in order.. primary keys first and then unique indexes. Originally I didn't have the option to manually set constraints but felt it was a must so I added this feature. For most purposes the auto method of assigning a constraint works quite well though and simplifies writing code. |
A question for you guys: I created the method So currently you could do: $this->db->table('user')->setBatch($userData)->upsertBatch(); The question is, we could forgo the $this->db->table('user')->setInsertBatch($userData)->upsertBatch(); What do you guys think? |
c01ae83
to
017e8ed
Compare
Here is a sneak peak at my next installment.. should you guys accept this PR. // upsert from query rather than data set
$fromQuery = $db->table('user_loggin')
->select('users.id, MAX(user_loggin.login_date) AS last_login')
->join('users','users.id = user_loggin.userid','inner')
->groupBy('users.id');
$builder = $db->table('users')
->fromQuery($fromQuery)
->onConstraint('id')
->updateFields('last_login')
->upsert();
// same can work with inserts
$builder = $db->table('table_name')
->fromQuery($fromQuery)
->ignore(true)
->insert();
// can work with raw SQL too
$fromQuery = <<<'SQL'
SELECT users.id, MAX(user_loggin.login_date) AS last_login
FROM user_login
INNER JOIN users ON users.id = user_login.userid
GROUP BY users.id
SQL;
$builder = $db->table('users')
->fromQuery($fromQuery)
->onConstraint('id')
->updateFields('last_login')
->upsert(); |
To be honest, the $builder->setBatch($data)->updateBatch(); I think it would be more logical to see the method name as At the same time, the And if I had to choose between the options you suggested, I would choose the third one. $builder->set(data); // ->insert()/update()/upsert() Both for single insert/update and batch. |
The set() method already works. It doesnt work for multiple records. Hense the setBatch() as its sister function. I agree with setUpsertBatch(). I guess I was thinking to consolidate them but that would cause other issues. It would be nice if set() did them all. |
@lonnieezell @paulbalandan @MGatner @michalsn @samsonasik @kenjis |
…to-error chore: Sphinx convert warning into error
…eTable docs: improve Forge::createTable() change description
fix: Email class may not log an error when it fails to send
feat: add IntBoolCast for Entity
Conflicts: user_guide_src/source/installation/upgrading.rst
Co-authored-by: kenjis <[email protected]>
Co-authored-by: kenjis <[email protected]>
…odeIgniter4 into UpsertUpsertBatch
@kenjis I screwed this up trying to fix a conflict. Any idea of what to do? |
What command did you run? |
I was using github desktop. I ran rebase UpsertUpsertBatch on 4.3 |
It was suppose to add like 11 commits on top of 4.3 |
I've pushed my backup of your branch in my repository: |
So how do I use your backup? |
I recommend you create a new branch as a backup before running destructive commands:
Fetch my repository:
Remove the existing branch:
Checkout:
|
|
I have the files. I'll just create a new branch and new PR. |
If you don't use SSH, use HTTPS link.
|
This PR adds Upsert and UpsertBatch methods to builder.
Checklist: