Giter Site home page Giter Site logo

dibi's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dibi's Issues

inserting blank row

$dibiConnection->insert("table", array());

generates sql query

insert into `table` () values (null)

which fails. It should generate

insert into `table` () values ()

I need it for inserting rows where id is automatically generated and where I don't need anything else.

DateTime & NULL

Hodila by se kontrola co vrací DateTime::format() (nebo jeho potomek),

protože pokud vrátí přesně typ NULL (možná to zní divně, ale je to v určitých případech potřeba) tak to poskládá chybný dotaz.

Přecejenom sloupec typu 'timestamp' v databázi může být taky NULL

příklad: http://gist.github.com/644588

Class DibiNettePanel not loaded

Calling dibi::connect throws Fatal error in DibiConnection on line 123, stating that class DibiNettePanel does not exist. Possible solution is to simply require it:

require_once DIR."/../Nette/DibiNettePanel.php";

DibiFluent cloning

Klonování DibiFluentu vůbec nefunguje.

$fluent = $dibiConnection->select("*")->from("table");
$f = clone $fluent;
echo $f;

nevypíše nic.

$fluent = $dibiConnection->select("*")->from("table");
$f = clone $fluent;
$f->removeClause("select")->select("count(*)");
echo $f;

pro změnu vypíše:

SELECT count(*) DISTINCT count(*) FROM count(*) WHERE count(*) GROUP BY count(*) HAVING count(*) ORDER BY count(*) LIMIT count(*) OFFSET count(*).

DibiProfiler a MAX_LENGTH

Dlzku SQL ovplyvnuje konstanta MAX_LENGTH. Je mi jasne, ze pokial profiler pouziva Firebug a FirePHP, je potrebne kontrolovat objem dat v hlavicke. Ale pri novom NetteBar-e uz take obmedzenie myslim nie je potrebne.

Samotny SQL profiler je potom zbytocny, kedze vacsinou prvych 500 znakov zo select-u je naprd, vacsinou to podstatne sa deje prave na konci :) Bolo by mozne dlzku SQL menit podla potreby ? Nieco ako Debug::$maxLen.

Mysql(i) getAffectedRows()

V souboru: https://github.com/dg/dibi/blob/master/dibi/drivers/mysqli.php#L198 (metoda getAffectedRows) je uvedeno v komentari, ze metoda vraci FALSE pri chybe, ale podle PHP dokumentace a zdrojoveho kodu to neni pravda:

http://www.php.net/manual/en/mysqli.affected-rows.php
https://github.com/php/php-src/blob/master/ext/mysqli/mysqli_api.c (doufam, ze odkazuju spravne)

Pri chybe se vraci -1.

Mohl by nekdo overit, ze se nemylim?
Diky


Narazil jsem na to, kdyz jsem cetl: http://stackoverflow.com/questions/7368225/how-do-i-tell-when-a-mysql-update-was-successful-versus-actually-updated-data

chybny arg

DibiProfiler::__construct() L56
miesto call_user_func('Nette\Diagnostics\Debugger', $this);
ma byt call_user_func('Nette\Diagnostics\Debugger::addPanel', $this);

Dibi Fluent a JOIN SELECT

Vypadá to na malý bug v Dibi fluent:

Pokud provedu

dibi::select('*')->from('jablka');

dostávám krásný výpis tabulky jablka.

Pokdu ale takovýto výpis chci joinnout:

echo dibi::select('*')->from('krabice_na_jablka', 'k')->join(
   dibi::select('*')->from('jablka'), 'j')->on('k.jablka_id = j.id');

Asi se to nějak zacyklí, protože to končí fatal errorem s vyčerpáním paměti.

Řešení problému je např. následující:

echo dibi::select('*')->from('krabice_na_jablka', 'k')->join(
   '('.dibi::select('*')->from('jablka').')', 'j')->on('k.jablka_id = j.id');

Tedy manuální dopsání závorek k joinovanému selectu - s ním vše funguje v pořádku.

TINYINT is detected as CHAR in MySQLi

DibiMySqliDriver::getColumnsMeta() detects TINYINT column as CHAR, because constants MYSQLI_TYPE_TINY and MYSQLI_TYPE_CHAR have same value.

(CHAR column is detected as MYSQLI_TYPE_STRING)

Incorrect table identifier quoting in PostgreSQL

This query:

WITH RECURSIVE user_privileges AS (
    SELECT
        ur1."id",
        ur1.id_user_parent,
        ur1.login,
        1 AS sort_order
    FROM
        "[user"] ur1
    WHERE
        ur1.login='guest'
    UNION
    SELECT
        ur2."id",
        ur2.id_user_parent,
        ur2.login,
        2 AS sort_order
    FROM
        "[user"] ur2
        JOIN
        user_privileges ups1
        ON(ur2.id_user_parent=ups1."id" OR ur2."id"=ups1.id_user_parent)
    WHERE
        ur2.login<>'guest'
)
SELECT
    *
FROM
    user_privileges
ORDER BY
    sort_order,
    "id",
    "id_user_parent"
;

which is the result of calling dibi::test($sql, UserModel::$user_login, UserModel::$user_login), where $sql is:

$sql = '
WITH RECURSIVE user_privileges AS (
    SELECT
        ur1.[id],
        ur1.id_user_parent,
        ur1.login,
        1 AS sort_order
    FROM
        [' . self::TABLE_USERS . '] ur1
    WHERE
        ur1.login=%s
    UNION
    SELECT
        ur2.[id],
        ur2.id_user_parent,
        ur2.login,
        2 AS sort_order
    FROM
        [' . self::TABLE_USERS . '] ur2
        JOIN
        user_privileges ups1
        ON(ur2.id_user_parent=ups1.[id] OR ur2.[id]=ups1.id_user_parent)
    WHERE
        ur2.login<>%s
)
SELECT
    *
FROM
    user_privileges
ORDER BY
    sort_order,
    [id],
    [id_user_parent]
';

and value of UserModel::$user_login is guest, fails, because Dibi doesn't rewrite [user] to "user" as it is necessary but it rewrites it to "[user"] instead.

If I use %n in $sql instead of [user], I get "[user]" instead of "user" (I call dibi::test($sql, self::TABLE_USERS, UserModel::$user_login, self::TABLE_USERS, UserModel::$user_login) in this case). This throws an SQL translate error exception.

Database: PostgreSQL.
Dibi: Dibi 1.3-dev (revision 550be3b released on 2010–04–06).

dibi won't connect to Nette's Debugbar

Problém je na řádku 28 v dibi.php, tato implementace háže:
Argument 1 passed to Nette\Debug::addPanel() must implement interface Nette\IDebugPanel, instance of DibiProfiler given

Opravou je z interface_exists('Nette\IDebugPanel', FALSE) vyhodit FALSE. Chyba se projevuje na Nette 2.0-dev z 24.9. v dibi balíku při aktivaci profileru pomocí config.ini.

DibiRow nededi od DibiObject

DibiRow v najnovsej verzii 1.3 nededi od DibiObjectu a iba implementuje potrebne rozhrania cim vsak obera o funkcionalitu objekty, ktore chce programator nastavit ako setRowClass objekty.

Bolo by lepsie ak by dedil od DibiObjectu aby aj classes, ktore budu v buducnu ako potencionalne entity mohli vyuzivat silu DibiObjectu.

SQL injection přes limit v DibiFluent

Pokud do limitu v limitu v DibiFluent vložím SQL kód, tak se v klidu vykoná. Ono je to vlastně správně, protože v limit nemusí být jen číslo, ale může tam být výraz. Přesto ale v 99% případů tam bude jen číslo.

  $sql->limit(" 1; drop table inovice"); // projde a vykoná se

Správné použití by tedy nejspíš bylo

  $sql->limit("%i", " 1; drop table inovice");

Jenže to je dost psaní, když u všech limitů používám jen čísla. Ideální chování by tedy bylo, kdyby se limit validoval vždy jako int a jen přes modifikátor %sql by to šlo donutit k něčemu jinému. Samozřejmě je to ale BC break, takže by na to nejspíš musela být nějaká volba "strictLimits"

To samé pak platí pro offset. U jiných konstrukcí to problém není a pouze u limit/offset podvědomě očekávám automatickou validaci.

U sebe jsem to dočasně vyřešil následujícím kódem v DibiFulent->__call, ale určitě to není ideální řešení

if(($clause == "LIMIT" || $clause == "OFFSET") && is_array($args) && count($args) == 1 && $args[1] !== false) {
    $args = array((int)trim($args[0]));
}

EDIT: Konkrétně ten DROP TABLE v MySQL stejně neprojde, ale tohle už třeba ano:

  $sql->limit(" 1; union(select group_concat(user) from(mysql.user))"); 

Autoloading třídy \DibiNettePanel

Hledal jsem důvod, proč se mi nezobrazuje Debug Panel v Nette při použití dibi bez použití statického dibi::__něco__. Přestože mám v konfiguraci Debug Panel zapnutý, nezobrazí se.

O vytvoření a napojení DibiNettePanelu se stará kontruktor ve tříde DibiConnection. Je nějaký důvod, proč je se kontrola na vytvoření panelu provádí právě takto?

<?
if (class_exists('DibiNettePanel', FALSE)) {
    $panel = new DibiNettePanel(isset($profilerCfg['explain']) ? $profilerCfg['explain'] : TRUE, $filter);
    $panel->register($this);
}
?>

Osobně bych uvítal například toto řešení:

<?
if (defined('NETTE') && class_exists('DibiNettePanel')) {
    $panel = new DibiNettePanel(isset($profilerCfg['explain']) ? $profilerCfg['explain'] : TRUE, $filter);
    $panel->register($this);
}
?>

Pokud mám projekt postavený na Nette, tak se použije pro DibiNettePanel autoloading a všechno krásně běží. Pokud Nette používám jen jako pomocnou knihovnu, tak mě to zajímat nemusí, protože konstanta NETTE je edfinována v loader.php, který v tomto případě nepoužiju. A pokud panel pro Dibi nechci vůbec, tak to jednoduše vypnu v konfiguraci.

Pokud mám poslat Pull Request, stačí komentář.

BUG v substitucích, asi někde probíhá cache

Následující kód:

$connection = dibi::connect(Environment::getConfig('database'));

dibi::addSubst('id', 'A.id');
dump($connection->translate('[:id:]'));
dibi::removeSubst('id');

dibi::addSubst('id', 'B.id');
dump($connection->translate('[:id:]'));

vypíše:

"`A`.`id`" (8)
"`A`.`id`" (8)

očekávaný výstup je:

"`A`.`id`" (8)
"`B`.`id`" (8)

Verze: 1.3-dev 8dc164d released on 2010-08-05

Snad tohle pomůže: U toho translate dělají problém hranaté závorky, samotné ':id:' se překládá správně (tedy substituuje se za A i za B), problém je s identifikátorem, tj. '[:id:]'.

Bude to asi tím, že se cachují identifikátory jako třída DibiLazyStorage a identifikátor se substitucí tam přetrvá i když se substituce změní.

Komentáře v SQL dotazu

$result = dibi::query("-- ".__FILE__.":".__LINE__.": Hello world
                    SELECT 'hello world'
            ")->fetchSingle();

Výsledný SQL dotaz:

-- /var/www/index.php':83:' Hello world
SELECT 'hello world'

Ve výsledku jsou navíc apostrofy u dvojteček.

Přidáme-li otazník:

$result = dibi::query("-- ".__FILE__.":".__LINE__.": Hello world ?
                    SELECT 'hello world'
            ")->fetchSingle();

Výsledek: SQL translate error

-- /var/www/index.php':83:' Hello world **Extra
placeholder**
SELECT 'hello world'

Trošku větší SQL dotazy pak dokážou generovat i chyby jako "DateTime::__construct(): Failed to parse time string (AND start_time <= %d) at position 0 (A): The timezone could not be found in the database". Samozřejmě, SQL dotaz je zcela správně a po odstranění komentáře na prvním řádku funguje.

Ten komentář na začátku měl sloužit k identifikaci dotazu v logu a chybových hlášeních.

Navíc v tom ladicím toolbaru od Nette chybí "explain" u takto okomentovaného dotazu a komentáře nejsou správně zvýrazněny.

detectTypes pro typ decimal vrací string

Pokud je sloupec typu decimal (8,3) a z databáze se čte celé číslo, mysql vrátí třeba "123.000". V dibi se detekuje jako decimal, takže se použije float. Na řádku 516 v DibiResult (metoda normalize) se ale provádí ještě jedna kontrola:

$row[$key] = (string) ($tmp = (float) $value) === $value ? $tmp : $value;

Pokud se pak vypisuje a ve sloupci decimal mám v jednom řádku hodnotu "123.001" a v druhém "123.000", tak první se převede správně na float, ale druhý se vrátí jako string.

Testováno na MySQL se stable dibi 2.0.1

problem with dibi::getConnection()->getDatabaseInfo()->getTables() on empty db (postgre driver)

There is a problem getting array of tables if database is empty while using postgre driver.

Problem is in postgre.php in GetTables(). If there are no rows in resultSet, pg_fetch_all() returns FALSE . And this cause problems in DibiDatabaseInfo.php in init() method on line 115. Foreach expects it to be array instead and it throws warning 'Invalid argument supplied for foreach()'.

fix:


diff --git a/libs/dibi/drivers/postgre.php b/libs/dibi/drivers/postgre.php
index 6fbb560..f07d138 100644
--- a/libs/dibi/drivers/postgre.php
+++ b/libs/dibi/drivers/postgre.php
@@ -426,7 +426,7 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
                ");
                $res = pg_fetch_all($this->resultSet);
                $this->free();
-               return $res;
+               return ($res === false ) ? array() : $res;
        }

dibi.minified.com

There is not any dibi.minified.php file... Can it be added please?

Mysql, BigInt a detekce typu

Pokud je v sloupeček typu BIGINT (vysledováno v MySQL databázi), dibi jej označí jako dibi::INTEGER (při automatickém přetypování). Pro 32b systémy je ale int v PHP jenom +/- 2 mld, tudíž se do něj hodnota bigintu z databáze nevejde a výsledek ve vrácených datech přeteče velikost intu (PHP_INT_SIZE). Pokud se provede přetypování na float, již je to v PHP v pořádku.

Mysql & Mysqli drivers: bug in detection unsigned columns

unsigned se špatně detekuje. Blbé pořadí parametrů ve funkci strstr viz
forum

Oprava zde: PetrP/dibi@9df5ec9

Zde je test:

/*
CREATE TABLE `test4` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `int` int(10) unsigned NOT NULL,
    `int2` int(10) unsigned zerofill NOT NULL,
    `int3` int(10) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB;
*/

$connetion = new DibiConnection(array(
    'driver' => 'mysql',
    'username' => 'root',
    'database' => 'test',
));

T::note(get_class($connetion->getDriver()));
foreach ($connetion->getDriver()->getColumns('test4') as $column)
{
    T::dump($column['unsigned'], $column['name']);
}

$connetion = new DibiConnection(array(
    'driver' => 'mysqli',
    'username' => 'root',
    'database' => 'test',
));

T::note(get_class($connetion->getDriver()));
foreach ($connetion->getDriver()->getColumns('test4') as $column)
{
    T::dump($column['unsigned'], $column['name']);
}


__halt_compiler() ?>
------EXPECT------
DibiMySqlDriver

id: bool(TRUE)

int: bool(TRUE)

int2: bool(TRUE)

int3: bool(FALSE)

DibiMySqliDriver

id: bool(TRUE)

int: bool(TRUE)

int2: bool(TRUE)

int3: bool(FALSE)

Privátní proměnné třídy DibiDataSource

Navrhuji některé privátní proměnné této třídy změnit na protected, aby se s nimi dalo dále pracovat ať už v extension metodách nebo v potomcích. Už jsem se dostal vícekrát do situace, kdy by se to hodilo. Momentálně by se to hodilo k implementaci metody reverse().

lazy connection nefunguje s lazy disconnection

Připojuju se v nette 0.9.7 v bootstrap pomoci

$application->onStartup[] = 'BaseModel::connect';
$application->onShutdown[] = 'BaseModel::disconnect';

database.lazy = true

a kdyz se na databazi nedotazu vubec (kešuju), tak mi vyhodí disconnect warning:
mysqli_close() expects parameter 1 to be mysqli, null given in C:..\libs\dibi\drivers\mysqli.php on line 146

používám dibi 1.3 ale v latest to taky hází tohle

takže předpokládám, že connect je lazy, ale disconect s timhle vůbec nepočítá...

DibiConnection::connect() není public.

Při rozšiřování DibiConnection (extensionMethod) je potřeba se připojit k databazi, protože může být nastaveno lazy připojení.

Bylo by dobré kdyby DibiConnection::connect() bylo public (DibiConnection::disconnect() public je)

Momentálně to řeším velmi ošklivým $connection->sql('');

Úprava je k dispozici zde: PetrP/dibi@9494061

Zalamování textu SQL dotazu rozdělí datum a čas

Dibi automaticky zalamuje text SQL dotazu, zřejmě podle mezer, pokud mám porovnávání data pomocí DATE_FORMAT se zadaným datem, rozlomí mi dibi např. 2010-11-18 10:00:00 na dva řádky (stává se pouze v případě příliš dlouhého řádku předpokládám):

2010-11-18
10:00:00

což způsobuje to, že porovnání následně nefunguje. Ozkoušeno pouze na MySQL.

bad colon interpreting in sql in dibi::query($sql)

dibi::query('RENAME TABLE table TO table_2010-05-17_03:06:53;');
failed with "InvalidStateException - Missing substitution for '06' expression."

mysql do this command right, so this sql command is OK.

MSSQL reflector - jiná hodnota pro neexistující položku size než v ostatních driverech

Metoda getColumns() v mssql.reflector.php vrací v položce „size“ v případě chybějících dat FALSE, ostatní drivery (mysql.reflector.php a sqlite.reflector) vrací v tomto případě NULL – lze vyřešit nastavením defaultní hodnoty $size na NULL tedy :

  1. $size = false;
    nahradit za:
  2. $size = NULL;

pak bude chování metody stejné jako při použití ostatních driverů.

(SELECT ...) UNION (SELECT ...) není označen jako SELECT -> žádný explain

Mějme dotaz s UNIONem, který chceme třídit:

(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;

pak tento dotaz není označen jako IDibiProfiler::SELECT (viz DibiConnection.php 334) a tím pádem není nabídnuta možnost explainu dotazu v DibiProfileru.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.