Acerca de uuids, claves primarias y bases de datos

El artículo está dedicado a versiones alternativas de controladores Qt para trabajar con bases de datos. En general, no hay tantas diferencias con los controladores Qt nativos, solo un par: 1) Soporte de tipo UUID; 2) Trabajar con la entidad "Transacción" como con un objeto independiente. Pero estas diferencias llevaron a una revisión significativa de la implementación del código de las soluciones Qt originales y cambiaron el enfoque para escribir código de trabajo.





Clave principal: ¿UUID o entero?

Me familiaricé por primera vez con la idea de usar UUID como clave principal en 2003, mientras trabajaba en un equipo de delfistas. Hemos desarrollado un programa para la automatización de procesos tecnológicos en producción. El DBMS jugó un papel importante en el proyecto. En ese momento era FireBird versión 1.5. A medida que el proyecto se hizo más complejo, se hizo difícil utilizar identificadores enteros como claves primarias. Describiré un par de dificultades:





  • Un problema de arquitectura: de vez en cuando los clientes enviaban datos de referencia para incluirlos en una nueva versión del kit de distribución. A veces, los directorios contenían las claves primarias que ya estaban en nuestra base de datos. Tuve que eliminar las colisiones en el proceso de agregación de datos. Los problemas no terminaron ahí: al implementar un nuevo kit de distribución, periódicamente se producían colisiones inversas.





  • : SELECT-, ( ). . . , , 2003 , - - .





UUID- , . UUID- , , SELECT- , . FireBird 1.5 UUID-, 32 ( UUID- ). , .





UUID- : 1) ; 2) . , . , , UUID-.





: UUID vs Integer MS SQL " – GUID ?"





FireBird

2012 FireBird. . QtFramework. FireBird 2.5 UUID-. : " Qt- FireBird QUuid?" Qt- UUID-. , , .





""

Qt- FireBird 2018 . . - , , ́ . . FireBird, . PostgreSQL, .





. Qt-FireBird . , Qt-, , : ( ) ( "" Driver). Qt- . , , : ( - ). Oracle, PostgreSQL, MS SQL ODBC. FireBird , API . , Qt-FireBird .





(2-3) , . . . , : , , , , sql- , . , . " - ". sql- .





"", , , . , "" , . , "" , , . , COMMIT ROLLBACK. , . Qt-.





, . (Driver) . , , . .





Qt-, :





- : " ?! ' - ', !" , , , , "" ODBC . , - , .





void function3(int value3)
{
    db::firebird::Driver::Ptr dbcon = fbpool().connect();
    db::firebird::Transaction::Ptr transact3 = dbcon->createTransact();
    QSqlQuery q3 {db::firebird::createResult(transact3)};

    if (!transact3->begin())
        return;
        
    if (!q3.prepare("INSERT INTO TABLE3 (VALUE3) VALUES (:VALUE3)"))
        return;
        
    sql::bindValue(q3, ":VALUE3" , value3);
    
    if (!q3.exec())
         return;

    transact3->commit();
}

void function2(int value2)
{
    db::firebird::Driver::Ptr dbcon = fbpool().connect();
    db::firebird::Transaction::Ptr transact2 = dbcon->createTransact();
    QSqlQuery q2 {db::firebird::createResult(transact2)};

    if (!transact2->begin())
        return;

    if (!q2.prepare("SELECT * FROM TABLE2 WHERE VALUE2 = :VALUE2"))
        return;
        
     sql::bindValue(q2, ":VALUE2 " , value2);
     
     if (!q2.exec())
         return;
         
    while (q2.next())
    {
        qint32 value3;
        sql::assignValue(value3, q2.record(), "VALUE3");
        function3(value3);
    }
}

void function1()
{
    db::firebird::Driver::Ptr dbcon = db::firebird::pool().connect();
    db::firebird::Transaction::Ptr transact1 = dbcon->createTransact();
    QSqlQuery q1 {db::firebird::createResult(transact1)};
    
    if (!transact1->begin())
        return;
        
    if (!sql::exec(q1, "SELECT * FROM TABLE1"))
        return;
        
    while (q1.next())
    {
        QSqlRecord r = q1.record();
        QUuidEx  id;
        qint32   value1;
        qint32   value2;
        sql::assignValue(id     , r, "ID     ");
        sql::assignValue(value1 , r, "VALUE1 ");
        sql::assignValue(value2 , r, "VALUE2 ");
        ...
        function2(value2);
    }
}
      
      



(1-3) . . QSqlQuery. ROLLBACK- SELECT- COMMIT- .





sql-. .





void function3(db::firebird::Transaction::Ptr transact, int value3)
{
    QSqlQuery q3 {db::firebird::createResult(transact)};
    //  - 
}

void function2(db::firebird::Transaction::Ptr transact, int value2)
{
    QSqlQuery q2 {db::firebird::createResult(transact)};
    //  - 
    function3(transact, value3);
}

void function1()
{
    db::firebird::Driver::Ptr dbcon = db::firebird::pool().connect();
    db::firebird::Transaction::Ptr transact = dbcon->createTransact();
    QSqlQuery q1 {db::firebird::createResult(transact)};
    
    if (!transact->begin())
        return;
        
    while (q1.next())
    {
        //  - 
        function2(transact, value2);
    }
    transact->commit();
}
      
      



PostgreSQL

2020 . : PostgreSQL. 18- , . PostgreSQL FireBird. Qt, , . Qt- : PREPARE EXECUTE. , , . , " ", PostgreSQL API. libpqxx , . " ". , . , . , , PostgreSQL . , . . singleConnect()



, . . singleConnect()



FALSE



. , . . , . .





MS SQL

MS SQL. , . MS SQL ODBC. PostgreSQL: - . , OLE DB MS SQL , ODBC . , "" . , NULL-. , .





Driver

Qt-. :





  • beginTransaction();





  • commitTransaction();





  • rollbackTransaction().





"" Qt-.





, , , . :





  • tables();





  • record();





  • primaryIndex();





  • formatValue();





  • escapeIdentifier().





. , , . , , .





, : "Forward Only". , , . , , SqlCachedResult



. - Qt-.





Driver



abortOperation()



, sql-, "" . Result



size2()



, sql-. size2()



, resultSize(const QSqlQuery&)



. .





GPL/LGPL 2.1. SqlCachedResult



, Qt . . PostgreSQL, , ( ). , : LGPL. , .





ALog, SharedTools.





-

. : FireBird, PostgreSQL, MS SQL. , . SharedTools .





QtCreator, QBS. :





  1. db_demo_project.qbs - ( 2-4);





  2. db_demo_firebird.qbs - FireBird ( FireBird-);





  3. db_demo_postgres.qbs - PostgreSQL ( libpq-dev);





  4. db_demo_mssql.qbs - MS SQL.





Linux, . Windows FireBird- (), .





- :





  • /tmp/db-demo-firebird.log





  • /tmp/db-demo-mssql.log





  • /tmp/db-demo-postgres.log





, . , - .





, , , : ", , . ?!" , !





Gran parte de mi trabajo y el trabajo de mis compañeros se ha invertido en la creación de pilotos, se ha gastado mucha vida. Conociendo la aversión de los programadores por las dependencias externas, no tengo la ilusión de que las soluciones presentadas se utilizarán "tal cual". Admito que alguien decide "quemarse con una plancha caliente" ALog y reemplazarlo con algo propio; no me importará (hago esto yo mismo con otros registradores;) En cualquier caso, si nuestras soluciones le ahorran tiempo a alguien, o servir como punto de partida para nuevas ideas - ¡será bueno!








All Articles