Asked  8 Months ago    Answers:  5   Viewed   38 times

How are they different? Here's what I'm thinking, but I'm not sure....

If you use pre-incrementation, for example in a for loop with ++j, then you are basically saying: "Make a copy of the value of j for use in the loop, then increment j, then go through the statements in the loop with the copy of j." If you are using post-incrementation in the same loop j++, then you are basically saying: "Make a copy of the value of j for use in the loop, then go through the statements in the loop with the copy of j, then increment j."

The reason I'm unsure is because I've created a for loop that multiplies the value of j by 10 and then outputs the result for j=1 through j=12, using both post- and pre-incrementation. The human readable output is exactly the same with post- and pre-incrementation. I'm thinking, 'How are the outputs exactly the same if there isn't some kind of copy operation involved?'

So, I'm guessing the difference between pre- and post-incrementation truly becomes important, in php, when I use references (which act as pointers in php) rather than names for return values? This would be because copies of references aren't made, so pre-incrementation would be: "Increment j, then go through the statements in the loop with the changed value of j, then increment j again...," whereas post-incremetation would look like: "Use the value of j for the statements in the loop, then change the value of j, then go through the loop with the new value of j..."

 Answers

97

Pre- or post-incrementing do not magically delay things until later. It's simply inline shorthand.

enter image description here

// pre-increment
$var = 5;
print(++$var); // increments first, then passes value (now 6) to print()

// post-increment
$var = 5;
print($var++); // passes value (still 5) to print(), then increments

Now let's look at a loop.

for ($i = 0; $i < 9; $i++) {
    print($i);
}

The last part of the loop declaration (the $i++) is simply the statement to execute after each time through the loop. It "passes" the value to nowhere, then increments it. $i isn't used anywhere at that time. Later when the next statement is executed (print($i);), the value of $i has already increased.

// add 1, then do nothing with $i
for ($i = 0; $i < 9; ++$i) {}

// do nothing with $i, then add 1
for ($i = 0; $i < 9; $i++) {}

Whichever way you do it, $i will be the same within the loop.


If it helps, you can think of them as small routines that kind of do this:

// ++$i
{
    $i = $i + 1;
    return $i;
}

// $i++
{
    return $i;
    $i = $i + 1;
}

As I reread your question, I think the confusion is more with how the loop works than how increment operators work. Keeping in mind that the increment is a straightforward, all-at-once operation, here's how third expression in the loop works.

// here's a basic loop
for ($i = 0; $i < 9; $i++) {
    // do loop stuff
    print($i);
}

// this is exactly what happens
for ($i = 0; $i < 9; ) {
    // do loop stuff
    print($i);

    $i++;
}

Just because that last line can be put in the loop declaration doesn't give it any special powers. There are no references or anything used behind the scenes. The same $i variable is seen both inside and outside the loop. Every statement inside or outside the loop directly looks up the value of $i when necessary. That's it. No funny business.

Wednesday, March 31, 2021
 
RahulG
answered 8 Months ago
41

PHP follows Perl's convention when dealing with arithmetic operations on character variables and not C's. For example, in PHP and Perl $a = 'Z'; $a++; turns $a into 'AA', while in C a = 'Z'; a++; turns a into '[' (ASCII value of 'Z' is 90, ASCII value of '[' is 91). Note that character variables can be incremented but not decremented and even so only plain ASCII characters (a-z and A-Z) are supported. Incrementing/decrementing other character variables has no effect, the original string is unchanged.

-> http://php.net/manual/en/language.operators.increment.php

Wednesday, March 31, 2021
 
Guesser
answered 8 Months ago
47

It sure does look to me that id_key is being passed by reference.

Some of those PDO libraries are coded in C. It's quite possible that in the innards the variables get corrupted there.

TBF you're passing a string as an argument that expects a numeric value, so from the standpoint of the functions you're using, the new value is the same as the old value (most text strings not containing digits = 0).

Friday, May 28, 2021
 
bumperbox
answered 5 Months ago
83

If you want to use prepare like that then you'll need to make a couple changes:

  1. The PostgreSQL driver wants to see numbered placeholders ($1, $2, ...) not question marks and you need to give your prepared statement a name:

     ActiveRecord::Base.connection.raw_connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1")
    
  2. The calling sequence is prepare followed by exec_prepared:

    connection = ActiveRecord::Base.connection.raw_connection
    connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1")
    st = connection.exec_prepared('some_name', [ id ])
    

The above approach works for me with ActiveRecord and PostgreSQL, your PG::Connection.open version should work if you're connecting properly.

Another way is to do the quoting yourself:

conn = ActiveRecord::Base.connection
conn.execute(%Q{
    delete from my_table
    where id = #{conn.quote(id)}
})

That's the sort of thing that ActiveRecord is usually doing behind your back.

Directly interacting with the database tends to be a bit of a mess with Rails since the Rails people don't think you should ever do it.

If you really are just trying to delete a row without interference, you could use delete:

delete()

[...]

The row is simply removed with an SQL DELETE statement on the record’s primary key, and no callbacks are executed.

So you can just say this:

MyTable.delete(id)

and you'll send a simple delete from my_tables where id = ... into the database.

Thursday, June 24, 2021
 
tdous
answered 5 Months ago
37

Using insert ... on conflict, you can't prevent the serial to auto-increment on conflicts. Postgres (just like other databases) does not guarantees that serials are sequential, as explained in the documentation:

Because smallserial, serial and bigserial are implemented using sequences, there may be "holes" or gaps in the sequence of values which appears in the column, even if no rows are ever deleted. A value allocated from the sequence is still "used up" even if a row containing that value is never successfully inserted into the table column. This may happen, for example, if the inserting transaction rolls back.

If you are running a lots of insert that end up in conflict, one way to limit the bleading would be to change the syntax to not exists:

insert into things (name)
select name
from (values ('desk')) v(name)
where not exists (select 1 from things t1 where t1.name = v.name)

Note that this still does not guarantee that serials will be sequential (refer to the above quote from the documentation).

Thursday, August 26, 2021
 
maerics
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :