def formatValueLike(self, type_: str, v: Any, upper: bool) -> str: """Return a string with the format value like.""" res = "IS NULL" if type_ == "bool": s = str(v[0]).upper() if s == str(QtWidgets.QApplication.translate("FLSQLite", "Sí")[0]).upper(): res = "=1" elif str(QtWidgets.QApplication.translate("FLSQLite", "No")[0]).upper(): res = "=0" elif type_ == "date": util = flutil.FLUtil() dateamd = util.dateDMAtoAMD(str(v)) if dateamd is None: dateamd = "" res = "LIKE '%%" + dateamd + "'" elif type_ == "time": t = v.toTime() res = "LIKE '" + t.toString(QtCore.Qt.ISODate) + "%%'" else: res = str(v) if upper: res = "%s" % res.upper() res = "LIKE '" + res + "%%'" return res
def test_basic_3(self) -> None: """Test basic 3.""" from pineboolib.fllegacy import flutil util = flutil.FLUtil() self.assertEqual( util.roundFieldValue("100.0193", "fltest", "double_field"), "100.02") self.assertEqual(util.sha1("123456"), "7C4A8D09CA3762AF61E59520943DC26494F8941B")
def formatValue(self, type_: str, v: Any, upper: bool) -> Optional[Union[int, str, bool]]: """Return a string with the format value.""" util = flutil.FLUtil() s: Any = None # TODO: psycopg2.mogrify ??? if type_ == "pixmap" and v.find("'") > -1: v = self.normalizeValue(v) if type_ in ("bool", "unlock"): if isinstance(v, str): if v[0].lower() == "t": s = 1 else: s = 0 elif isinstance(v, bool): if v: s = 1 else: s = 0 elif type_ == "date": s = "'%s'" % util.dateDMAtoAMD(v) elif type_ == "time": if v: s = "'%s'" % v else: s = "" elif type_ in ("uint", "int", "double", "serial"): s = v or 0 else: if v and type_ == "string": v = auto_qt_translate_text(v) if upper: v = v.upper() s = "'%s'" % v # if type_ in ("string", "stringlist", "timestamp"): # if v is None: # s = "NULL" # else: # if type_ == "string": # v = auto_qt_translate_text(v) # if upper: # v = v.upper() # # v = v.encode("UTF-8") # s = "'%s'" % v return s
def test_basic_2(self) -> None: """Test basic 2.""" from PyQt5 import QtCore from pineboolib.fllegacy import flutil util = flutil.FLUtil() self.assertEqual(util.buildNumber("123.4533", "", 2), "123.45") self.assertEqual(util.buildNumber("123.451000", "", 3), "123.451") self.assertEqual(util.buildNumber("123.451000", "", 1), "123.5") self.assertEqual(util.buildNumber("123.451000", "", 2), "123.45") self.assertEqual(util.buildNumber("-123.451000", "", 2), "-123.45") self.assertEqual(util.nameBD(), "temp_db") self.assertEqual(util.nameUser(), "memory_user") self.assertEqual(util.getIdioma(), QtCore.QLocale().name()[:2])
def test_sql(self) -> None: """Test sql functions.""" from pineboolib.fllegacy import flutil, flsqlcursor from pineboolib.qsa import qsa ar_1 = qsa.Array("idarea", "descripcion") ar_2 = qsa.Array("G", "area test 2") util = flutil.FLUtil() self.assertTrue( util.sqlInsert("flareas", ["idarea", "descripcion"], ["T", "area test 1"])) self.assertTrue(util.sqlInsert("flareas", ar_1, ar_2)) cur = flsqlcursor.FLSqlCursor("flareas") cur.select() self.assertEqual(cur.size(), 2) res_1 = util.sqlSelect("flareas", "COUNT(idarea)", "1=1") self.assertEqual(res_1, 2) res_2 = util.quickSqlSelect("flareas", "COUNT(idarea)", "1=1") self.assertEqual(res_2, 2) self.assertTrue( util.sqlUpdate("flareas", "descripcion", "area test modificado", "idarea ='T'")) self.assertEqual( util.quickSqlSelect("flareas", "descripcion", "idarea ='T'"), "area test modificado") self.assertTrue( util.execSql("SELECT COUNT(*) FROM flareas WHERE '1=1'", "default")) self.assertFalse( util.execSql("SELECT COUNT(*) FROG flareas WHERE '1=1'", "default")) self.assertTrue(util.sqlDelete("flareas", "idarea ='T'", "default")) cur.refresh() self.assertEqual(cur.size(), 1) self.assertTrue( util.quickSqlDelete("flareas", "idarea ='G'", "default")) cur.refresh() self.assertEqual(cur.size(), 0)
def test_field_functions(self) -> None: """Test field functions.""" from pineboolib.fllegacy import flutil util = flutil.FLUtil() self.assertEqual(util.formatValue("string", "uno", True), "'UNO'") self.assertEqual(util.formatValue("uint", 1233, False), "1233") self.assertEqual(util.formatValue("double", 1233, False), "1233") self.assertEqual(util.formatValue("bool", True, False), "1") self.assertTrue(util.fieldDefaultValue("bloqueo", "flareas")) self.assertFalse(util.fieldIsCompoundKey("idarea", "flareas")) self.assertTrue(util.fieldIsPrimaryKey("idarea", "flareas")) self.assertTrue(util.fieldAllowNull("icono", "flmodules")) self.assertFalse(util.fieldAllowNull("idarea", "flareas")) self.assertEqual(util.fieldAliasToName("Icono", "flmodules"), "icono") self.assertEqual(util.fieldNameToAlias("icono", "flmodules"), "Icono") self.assertEqual(util.fieldType("icono", "flmodules"), 6) self.assertEqual(util.fieldLength("descripcion", "flareas"), 100) self.assertEqual(util.fieldLength("idarea", "flareas"), 15) self.assertEqual(util.fieldLength("bloqueo", "flareas"), 0)
def test_basic_3(self) -> None: """Bad cursor.""" from pineboolib.application.database import pnsqlcursor from pineboolib.fllegacy import flutil cursor = pnsqlcursor.PNSqlCursor("Fltest") self.assertEqual(cursor.metadata().name(), "fltest") cursor.setAction("bad_Action") action = cursor.action() if action: self.assertEqual(action.name(), "bad_action") cursor.select() self.assertEqual(cursor.size(), 0) cursor.setAction("fltest") cursor.select() self.assertEqual(cursor.size(), 98) util = flutil.FLUtil() util.sqlDelete("fltest", "1=1", "dbAux") cursor.first() # while cursor.next(): # print("**", cursor.valueBuffer("string_field")) cursor.refresh() self.assertEqual(cursor.size(), 0)
def alterTable2(self, mtd1: str, mtd2: str, key: Optional[str], force: bool = False) -> bool: """Alter a table following mtd instructions.""" if not self.isOpen(): raise Exception("alterTable2: Database not open") return False if not self.db_: raise Exception("must be connected") util = flutil.FLUtil() old_mtd = None new_mtd = None if not mtd1: print( "FLManager::alterTable : " + util.translate("SqlDriver", "Error al cargar los metadatos.") ) else: xml = ElementTree.fromstring(mtd1) old_mtd = self.db_.connManager().manager().metadata(xml, True) if old_mtd and old_mtd.isQuery(): return True if old_mtd and self.hasCheckColumn(old_mtd): return False if not mtd2: print( "FLManager::alterTable : " + util.translate("SqlDriver", "Error al cargar los metadatos.") ) return False else: xml = ElementTree.fromstring(mtd2) new_mtd = self.db_.connManager().manager().metadata(xml, True) if not old_mtd: old_mtd = new_mtd if not old_mtd.name() == new_mtd.name(): print( "FLManager::alterTable : " + util.translate("SqlDriver", "Los nombres de las tablas nueva y vieja difieren.") ) if old_mtd and not old_mtd == new_mtd: del old_mtd if new_mtd: del new_mtd return False oldPK = old_mtd.primaryKey() newPK = new_mtd.primaryKey() if not oldPK == newPK: print( "FLManager::alterTable : " + util.translate("SqlDriver", "Los nombres de las claves primarias difieren.") ) if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return False if not force and self.db_.connManager().manager().checkMetaData(old_mtd, new_mtd): if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return True if not self.db_.connManager().manager().existsTable(old_mtd.name()): print( "FLManager::alterTable : " + util.translate( "SqlDriver", "La tabla %s antigua de donde importar los registros no existe." % old_mtd.name(), ) ) if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return False fieldList = old_mtd.fieldList() # oldField = None if not fieldList: print( "FLManager::alterTable : " + util.translate("SqlDriver", "Los antiguos metadatos no tienen campos.") ) if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return False fieldNamesOld = [] if not force: for it in fieldList: if new_mtd.field(it.name()) is not None: fieldNamesOld.append(it.name()) renameOld = "%salteredtable%s" % ( old_mtd.name()[0:5], QtCore.QDateTime().currentDateTime().toString("ddhhssz"), ) if not self.db_.connManager().dbAux(): if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return False # self.db_.connManager().dbAux().transaction() fieldList = new_mtd.fieldList() if not fieldList: LOGGER.warning( "FLManager::alterTable : " + util.translate("SqlDriver", "Los nuevos metadatos no tienen campos") ) if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return False q = pnsqlquery.PNSqlQuery(None, "dbAux") in_sql = "ALTER TABLE %s RENAME TO %s" % (old_mtd.name(), renameOld) LOGGER.warning(in_sql) if not q.exec_(in_sql): LOGGER.warning( "FLManager::alterTable : " + util.translate("SqlDriver", "No se ha podido renombrar la tabla antigua.") ) if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return False if not self.db_.connManager().manager().createTable(new_mtd): self.db_.connManager().dbAux().rollbackTransaction() if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return False self.db_.connManager().dbAux().transaction() if not force and key and len(key) == 40: c = pnsqlcursor.PNSqlCursor("flfiles", True, self.db_.connManager().dbAux()) # oldCursor.setModeAccess(oldCursor.Browse) c.setForwardOnly(True) c.setFilter("nombre='%s.mtd'" % renameOld) c.select() if not c.next(): # c.setModeAccess(c.Insert) # c.refreshBuffer() # c.setValueBuffer("nombre","%s.mtd" % renameOld) # c.setValueBuffer("contenido", mtd1) # c.setValueBuffer("sha", key) # c.commitBuffer() in_sql = ( "INSERT INTO flfiles(nombre,contenido,idmodulo,sha) VALUES ('%s.mtd','%s','%s','%s')" % ( renameOld, mtd1, self.db_.connManager() .managerModules() .idModuleOfFile("%s.mtd" % old_mtd.name()), key, ) ) LOGGER.warning(in_sql) q.exec_(in_sql) ok = False if force and fieldNamesOld: # sel = fieldNamesOld.join(",") # in_sql = "INSERT INTO %s(%s) SELECT %s FROM %s" % (new_mtd.name(), sel, sel, renameOld) # LOGGER.warning(in_sql) # ok = q.exec_(in_sql) if not ok: self.db_.connManager().dbAux().rollbackTransaction() if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return self.alterTable2(mtd1, mtd2, key, True) if not ok: oldCursor = self.conn_.cursor(self.dict_cursor()) # print("Lanzando!!", "SELECT * FROM %s WHERE 1 = 1" % (renameOld)) oldCursor.execute("SELECT * FROM %s WHERE 1 = 1" % (renameOld)) result_set = oldCursor.fetchall() totalSteps = len(result_set) # oldCursor = pnsqlcursor.PNSqlCursor(renameOld, True, "dbAux") # oldCursor.setModeAccess(oldCursor.Browse) # oldCursor.setForwardOnly(True) # oldCursor.select() # totalSteps = oldCursor.size() util.createProgressDialog( util.translate("SqlDriver", "Reestructurando registros para %s...") % new_mtd.alias(), totalSteps, ) util.setLabelText(util.translate("SqlDriver", "Tabla modificada")) step = 0 newBuffer = None newField = None listRecords = [] newBufferInfo = self.recordInfo2(new_mtd.name()) vector_fields = {} default_values = {} v = None for it2 in fieldList: oldField = old_mtd.field(it2.name()) if ( oldField is None or not result_set or oldField.name() not in result_set[0].keys() ): if oldField is None: oldField = it2 if it2.type() != pnfieldmetadata.PNFieldMetaData.Serial: v = it2.defaultValue() step += 1 default_values[str(step)] = v step += 1 vector_fields[str(step)] = it2 step += 1 vector_fields[str(step)] = oldField # step2 = 0 ok = True x = 0 for row in result_set: x += 1 newBuffer = newBufferInfo i = 0 while i < step: v = None if str(i + 1) in default_values.keys(): i += 1 v = default_values[str(i)] i += 1 newField = vector_fields[str(i)] i += 1 oldField = vector_fields[str(i)] else: i += 1 newField = vector_fields[str(i)] i += 1 oldField = vector_fields[str(i)] v = row[newField.name()] if ( (not oldField.allowNull() or not newField.allowNull()) and (v is None) and newField.type() != pnfieldmetadata.PNFieldMetaData.Serial ): defVal = newField.defaultValue() if defVal is not None: v = defVal if v is not None and newField.type() == "string" and newField.length() > 0: v = v[: newField.length()] if (not oldField.allowNull() or not newField.allowNull()) and v is None: if oldField.type() == pnfieldmetadata.PNFieldMetaData.Serial: v = int(self.nextSerialVal(new_mtd.name(), newField.name())) elif oldField.type() in ["int", "uint", "bool", "unlock"]: v = 0 elif oldField.type() == "double": v = 0.0 elif oldField.type() == "time": v = QtCore.QTime.currentTime() elif oldField.type() == "date": v = QtCore.QDate.currentDate() else: v = "NULL"[: newField.length()] # new_b = [] for buffer in newBuffer: if buffer[0] == newField.name(): new_buffer = [] new_buffer.append(buffer[0]) new_buffer.append(buffer[1]) new_buffer.append(newField.allowNull()) new_buffer.append(buffer[3]) new_buffer.append(buffer[4]) new_buffer.append(v) new_buffer.append(buffer[6]) listRecords.append(new_buffer) break # newBuffer.setValue(newField.name(), v) if listRecords: if not self.insertMulti(new_mtd.name(), listRecords): ok = False listRecords = [] util.setProgress(totalSteps) util.destroyProgressDialog() if ok: self.db_.connManager().dbAux().commit() if force: q.exec_("DROP TABLE %s CASCADE" % renameOld) else: self.db_.connManager().dbAux().rollbackTransaction() q.exec_("DROP TABLE %s CASCADE" % old_mtd.name()) q.exec_("ALTER TABLE %s RENAME TO %s" % (renameOld, old_mtd.name())) if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return False if old_mtd and old_mtd != new_mtd: del old_mtd if new_mtd: del new_mtd return True
def Mr_Proper(self) -> None: """Cleanup database like mr.proper.""" if not self.isOpen(): raise Exception("Mr_Proper: Database not open") util = flutil.FLUtil() if not self.db_: raise Exception("must be connected") self.db_.connManager().dbAux().transaction() qry = pnsqlquery.PNSqlQuery(None, "dbAux") qry2 = pnsqlquery.PNSqlQuery(None, "dbAux") qry3 = pnsqlquery.PNSqlQuery(None, "dbAux") # qry4 = pnsqlquery.PNSqlQuery(None, "dbAux") # qry5 = pnsqlquery.PNSqlQuery(None, "dbAux") steps = 0 self.active_create_index = False rx = Qt.QRegExp("^.*\\d{6,9}$") if rx in self.tables(): listOldBks = self.tables()[rx] else: listOldBks = [] qry.exec_( "select nombre from flfiles where nombre regexp" "'.*[[:digit:]][[:digit:]][[:digit:]][[:digit:]]-[[:digit:]][[:digit:]].*:[[:digit:]][[:digit:]]$' or nombre regexp" "'.*alteredtable[[:digit:]][[:digit:]][[:digit:]][[:digit:]].*' or (bloqueo=0 and nombre like '%.mtd')" ) util.createProgressDialog( util.translate("SqlDriver", "Borrando backups"), len(listOldBks) + qry.size() + 2 ) while qry.next(): item = qry.value(0) util.setLabelText(util.translate("SqlDriver", "Borrando registro %s") % item) qry2.exec_("DELETE FROM flfiles WHERE nombre ='%s'" % item) if item.find("alteredtable") > -1: if self.existsTable(item.replace(".mtd", "")): util.setLabelText(util.translate("SqlDriver", "Borrando tabla %s" % item)) qry2.exec_("DROP TABLE %s CASCADE" % item.replace(".mtd", "")) steps = steps + 1 util.setProgress(steps) for item in listOldBks: if self.existsTable(item): util.setLabelText(util.translate("SqlDriver", "Borrando tabla %s" % item)) qry2.exec_("DROP TABLE %s CASCADE" % item) steps = steps + 1 util.setProgress(steps) util.setLabelText(util.translate("SqlDriver", "Inicializando cachés")) steps = steps + 1 util.setProgress(steps) qry.exec_("DELETE FROM flmetadata") qry.exec_("DELETE FROM flvar") self.db_.connManager().manager().cleanupMetaData() # self.db_.connManager().driver().commit() util.destroyProgressDialog() steps = 0 qry3.exec_("SHOW TABLES") util.createProgressDialog( util.translate("SqlDriver", "Comprobando base de datos"), qry3.size() ) while qry3.next(): item = qry3.value(0) # print("Comprobando", item) # qry2.exec_("alter table %s convert to character set utf8 collate utf8_bin" % item) mustAlter = self.mismatchedTable(item, item) if mustAlter: conte = self.db_.connManager().managerModules().content("%s.mtd" % item) if conte: msg = util.translate( "SqlDriver", "La estructura de los metadatos de la tabla '%s' y su " "estructura interna en la base de datos no coinciden. " "Intentando regenerarla." % item, ) LOGGER.warning("%s", msg) self.alterTable2(conte, conte, None, True) steps = steps + 1 util.setProgress(steps) self.db_.connManager().dbAux().driver().transaction() self.active_create_index = True steps = 0 # sqlCursor = pnsqlcursor.PNSqlCursor(None, True, self.db_.connManager().dbAux()) engine = "MyISAM" if self.noInnoDB else "INNODB" convert_engine = False do_ques = True sqlQuery = pnsqlquery.PNSqlQuery(None, self.db_.connManager().dbAux()) sql_query2 = pnsqlquery.PNSqlQuery(None, self.db_.connManager().dbAux()) if sqlQuery.exec_("SHOW TABLES"): util.setTotalSteps(sqlQuery.size()) while sqlQuery.next(): item = sqlQuery.value(0) steps = steps + 1 util.setProgress(steps) util.setLabelText(util.translate("SqlDriver", "Creando índices para %s" % item)) mtd = self.db_.connManager().manager().metadata(item, True) if not mtd: continue fL = mtd.fieldList() if not fL: continue for it in fL: if not it or not it.type() == "pixmap": continue cur = pnsqlcursor.PNSqlCursor(item, True, self.db_.connManager().dbAux()) cur.select(it.name() + " not like 'RK@%'") while cur.next(): v = cur.valueBuffer(it.name()) if v is None: continue v = self.db_.connManager().manager().storeLargeValue(mtd, v) if v: buf = cur.primeUpdate() buf.setValue(it.name(), v) cur.update(False) # sqlCursor.setName(item, True) # self.db_.connManager().dbAux().driver().commit() sql_query2.exec_( "show table status where Engine='%s' and Name='%s'" % (engine, item) ) if not sql_query2.next(): if do_ques: res = QtWidgets.QMessageBox.question( QtWidgets.QWidget(), util.translate("SqlDriver", "Mr. Proper"), util.translate( "SqlDriver", "Existen tablas que no son del tipo %s utilizado por el driver de la conexión actual.\n" "Ahora es posible convertirlas, pero asegurése de tener una COPIA DE SEGURIDAD,\n" "se pueden peder datos en la conversión de forma definitiva.\n\n" "¿ Quiere convertirlas ?" % (engine), ), QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No, ) if res == QtWidgets.QMessageBox.Yes: convert_engine = True do_ques = False if convert_engine: conte = self.db_.connManager().managerModules().content("%s.mtd" % item) self.alterTable2(conte, conte, None, True) self.active_create_index = False util.destroyProgressDialog()
def Mr_Proper(self) -> None: """Clear all garbage data.""" LOGGER.warning("FLSQLITE: FIXME: Mr_Proper no regenera tablas") util = flutil.FLUtil() if self.db_ is None: raise Exception("MR_Proper: self.db_ is None") if not self.isOpen(): raise Exception("MR_Proper: Cannot proceed: SQLLITE not open") self.db_.connManager().dbAux().transaction() rx = Qt.QRegExp("^.*[\\d][\\d][\\d][\\d].[\\d][\\d].*[\\d][\\d]$") rx2 = Qt.QRegExp("^.*alteredtable[\\d][\\d][\\d][\\d].*$") qry = pnsqlquery.PNSqlQuery(None, "dbAux") qry2 = pnsqlquery.PNSqlQuery(None, "dbAux") qry3 = pnsqlquery.PNSqlQuery(None, "dbAux") steps = 0 item = "" rx3 = Qt.QRegExp("^.*\\d{6,9}$") # listOldBks = self.tables("").grep(rx3) listOldBks_prev = self.tables("Tables") listOldBks = [] for l in listOldBks_prev: if rx3.indexIn(l) > -1: listOldBks.append(l) qry.exec_("select nombre from flfiles") util.createProgressDialog( util.translate("SqlDriver", "Borrando backups"), len(listOldBks) + qry.size() + 5) while qry.next(): item = qry.value(0) if rx.indexIn(item) > -1 or rx2.indexIn(item) > -1: util.setLabelText( util.translate("SqlDriver", "Borrando regisro %s" % item)) qry2.exec_("delete from flfiles where nombre = '%s'" % item) if item.find("alteredtable") > -1: if item.replace(".mtd", "") in self.tables(""): util.setLabelText( util.translate("SqlDriver", "Borrando tabla %s" % item)) qry2.exec_("drop table %s" % item.replace(".mtd", "")) steps = steps + 1 util.setProgress(steps) for item in listOldBks: if item in self.tables(""): util.translate("SqlDriver", "Borrando tabla %s" % item) util.setLabelText( util.translate("SqlDriver", "Borrando tabla %s" % item)) qry2.exec_("drop table %s" % item) steps = steps + 1 util.setProgress(steps) util.setLabelText(util.translate("SqlDriver", "Inicializando cachés")) steps = steps + 1 util.setProgress(steps) qry.exec_("delete from flmetadata") qry.exec_("delete from flvar") self.db_.connManager().manager().cleanupMetaData() self.db_.connManager().dbAux().commit() util.setLabelText( util.translate("SqlDriver", "Vacunando base de datos")) steps = steps + 1 util.setProgress(steps) qry3.exec_("vacuum") steps = steps + 1 util.setProgress(steps) util.destroyProgressDialog()