phinx icon indicating copy to clipboard operation
phinx copied to clipboard

Precision and Scale bug mysql

Open HDias opened this issue 7 years ago • 9 comments

When I create table with column decimal, for example:

->addColumn(
                'id_usuario_inclusao', 
                'decimal', [
                    'default' => null,
                    'null' => false,
                    'precision' => 30,
                    'scale' => 0
                ])

the method protected function getColumnSqlDefinition() in Phinx\Db\Adapter\MysqlAdapter, no set precision and scale because the verification if ($column->getPrecision() && $column->getScale()) { not works.

If I set scale how true, 1 and more it works, for example:

->addColumn(
                'id_usuario_inclusao', 
                'decimal', [
                    'default' => null,
                    'null' => false,
                    'precision' => 30,
                    'scale' => true
                ])

My suggest is change the verification if to:

 if ($column->getPrecision() && $column->getScale()) {
            $def .= '(' . $column->getPrecision() . ',' . $column->getScale() . ')';
        } elseif ($column->getScale()) {
            $def .= '(' . 10 . ',' . $column->getScale() . ')';
        } elseif ($column->getPrecision()) {
            $def .= '(' . $column->getPrecision() . ',' . 0 . ')';
        }

HDias avatar Jan 14 '19 15:01 HDias

I think it should be simply

if ($column->getPrecision()) {
    $def .= '(' . $column->getPrecision() . ',' . $column->getScale() . ')';
}

I don't think it should any default for precision when only scale defined.

garas avatar Jan 14 '19 17:01 garas

I think it should be simply

if ($column->getPrecision()) {
    $def .= '(' . $column->getPrecision() . ',' . $column->getScale() . ')';
}

I don't think it should any default for precision when only scale defined.

Its necessary, (Precision, Scale) or (Precision) in mysql. (, Scale) not work (no change properties)

HDias avatar Jan 14 '19 18:01 HDias

There is no (Scale) in MySQL (and other DBs), so I think it is better to ignore scale than add it with some default (10, Scale).

There is (Precision, Scale) or (Precision) or not specified.

garas avatar Jan 14 '19 19:01 garas

There is no (Scale) in MySQL (and other DBs), so I think it is better to ignore scale than add it with some default (10, Scale).

There is (Precision, Scale) or (Precision) or not specified.

When the user set only scale, show the message INFO in terminal:

  • Only SCALE value no return results.

will be a good idea?

HDias avatar Jan 14 '19 20:01 HDias

Currently there is no output from MysqlAdapter, thus for consistency I would avoid messages.

There are exceptions used in that file, so maybe

if ($column->getPrecision() && $column->getScale()) {
    $def .= sprintf('(%d, %d)', $column->getPrecision(), $column->getScale());
} elseif ($column->getScale()) {
    throw new \InvalidArgumentException(sprintf(
        "'scale' option must be used together with 'precision' option on column '%s'",
        $column->getName()
    ));
}

garas avatar Jan 15 '19 10:01 garas

@HDias I see you've committed some changes to your fork. Will you be able to finish and submit PR?

garas avatar Jan 17 '19 11:01 garas

@HDias I see you've committed some changes to your fork. Will you be able to finish and submit PR?

Yes! I'll finish this changes today.

HDias avatar Jan 17 '19 13:01 HDias

PR open: https://github.com/cakephp/phinx/pull/1486

dereuromark avatar Jan 22 '19 18:01 dereuromark

Looking into this now. The behavior of the data providers is the same if you specify both precision and scale, or just precision (scale defaults to 0). If you specify neither then you get the following result:

mysql postgres sqlserver
precision 10 infinity 18
scale 0 infinity 0

As such, to make things as portable as possible, it's best to default to (18, 0) if no options are given for either, so that it's not possible to end up with breakage if you switch DB providers.

All adapters have varying levels of how they support precision, and so it should be unified as part of a solution PR (which I'm working on). SQLite technically supports having precision and scale, but it's not a true type value like other adapters, so it's especially wacky with decimal support.

MasterOdin avatar May 10 '20 05:05 MasterOdin