PEAR is archived and read-only

This mirror preserves historical PEAR package releases and metadata so existing references remain available.

Home » Internationalization » Translation2 » Bug #2631

Translation2_Admin::add() produces duplicates

Details

Submitted2004-10-27 14:11 UTC
Fromylf at xung dot org
Assignedquipo
StatusClosed
PackageTranslation2
PHP Version4.3.4
OSLinux Debian (testing)
Roadmaps(Not assigned)

Comments

[2004-10-27 14:11 UTC] ylf at xung dot org

Description:
------------
In bug #2570 I asked for an Admin:update() method, which you did include. Thanks for that.

But, the add() method performs in a pretty inconsistent manner. It should sometimes perform an update.

The point is that the string id and page id couple should form a unique key : there can't be two rows in the i18n table with both the same string id and page id, or the table is inconsistent. And this is not respected.

Currently add() means 'add a new string id', but one may think add() also means : 'add a new translation for this string id'. Of course, the documentation could state that for this later case, update() is the right way.

But I believe you have to do some extra checking, otherwise the tables may get inconsistent when someone adds twice the same string id.

After checking the reproduce code you may think that the closest solution to this issue would be to use the mysql REPLACE statement, but it won't work :

"Values for all columns are taken from the values specified in the REPLACE statement. Any missing columns are set to their default values, just as happens for INSERT."

(see: http://dev.mysql.com/doc/mysql/en/REPLACE.html)

So, to keep tables consistent, I guess you'll have to
- either issue more queries,
- or do some comparison between the cache and what's to be add()ed
- or use an sql constraint as "INDEX full_id (page_id,id)" which will result in a DB error if there's a duplicate row (the lightest and smartest to me, but is it portable ?)

Reproduce code:
---------------
<?php

error_reporting (E_ALL);

require_once 'PEAR.php';
require_once 'DB.php';
require_once 'Translation2/Admin.php';

$dsn = '';
$db =& DB::connect($dsn);

// Starting with an empty db : tables langs and i18n do not exist

$db->query('drop table if exists langs, i18n');

$tr =& Translation2_Admin::factory('DB', $db);

if (PEAR::isError($tr)) exit($tr->getMessage());

$newLang = array(
'lang_id' => 'en',
'table_name' => 'i18n',
'name' => 'english',
'meta' => 'some meta info',
'error_text' => 'not available');

$tr->createNewLang($newLang);

$newLang = array(
'lang_id' => 'fr',
'table_name' => 'i18n',
'name' => 'french',
'meta' => 'some meta info',
'error_text' => 'not available');

$tr->createNewLang($newLang);

// this works fine :
$tr->add('string1','page1',array('en' => 'string 1', 'fr' => 'texte 1'));

// now let's add an english only translation
$tr->add('string2','page1',array('en' => 'string 2'));

// and, subsequently, the french translation for the same string id
$tr->add('string2','page1',array('fr' => 'chaine 2'));

// and even, the english translation again for the same string id
$tr->add('string2','page1',array('en' => 'string 2'));

echo "<html><body><pre>";

echo "\n\n----------------------------------------\n";
echo "table : i18n\n";
echo "----------------------------------------\n";
$res =& $db->getAll("select * from i18n",array(),DB_FETCHMODE_ASSOC);
print_r ($res);

echo "</pre></body></html>";
?>

Expected result:
----------------
----------------------------------------
table : i18n
----------------------------------------
Array
(
[0] => Array
(
[page_id] => page1
[id] => string1
[en] => string 1
[fr] => texte 1
)

[1] => Array
(
[page_id] => page1
[id] => string2
[en] => string 2
[fr] => chaine 2
)

)

Actual result:
--------------
----------------------------------------
table : i18n
----------------------------------------
Array
(
[0] => Array
(
[page_id] => page1
[id] => string1
[en] => string 1
[fr] => texte 1
)

[1] => Array
(
[page_id] => page1
[id] => string2
[en] => string 2
[fr] =>
)

[2] => Array
(
[page_id] => page1
[id] => string2
[en] =>
[fr] => chaine 2
)

[3] => Array
(
[page_id] => page1
[id] => string2
[en] => string 2
[fr] =>
)

)