public function toSql()
    {
        if (is_null($this->table)) {
            // brak tabeli
            throw new \Exception("Please define table for select.");
        }

        // usuwam rzeczy zwiazane z przetwarzaniem zapytania
        $this->reset(true);

        // tworze bazowe zapytanie
        $alias = $this->alias;
        $table = $this->table;
        $quoteChar = $this->quoteChar();

        // build select
        $sql = "select\n";

        // columns
        $fields = array();

        // wybieram tylko te kolumny ktore nie sa ukryte
        foreach (array_keys($this->columns) as $field) {
            $column = $this->columns[$field];

            if ($column->isHidden()) {
                continue;
            }else{
                $fields[] = $field;
            }
        }

        // zliczam wszystkie kolumny
        $ccolumn = count($fields);
        $added = false;

        for ($i=0; $i < $ccolumn; $i++) {
            // pobieram zdefiniowana kolumne
            $column = $this->columns[$fields[$i]];

            if ($column->isHidden()) {
                // pomijam ukryte kolumny
                continue;
            }

            $value = $column->value();
            $calias = $column->alias();

            if (!is_null($calias)) {
                $calias = " as {$quoteChar}{$calias}{$quoteChar}";
            }else{
                $calias = "";
            }

            if(is_null($value)){
                $value = "null";
            }

            if ($i == $ccolumn-1) {
                // last column
                $sql .= "    {$value}{$calias}\n";
            }else{
                $sql .= "    {$value}{$calias},\n";
            }

            $added = true;
        }

        if ($added === false) {
            // jak nie ma kolumn to pobieram wszystkie
            $sql .= "    *\n";
        }

        $sql .= "from {$quoteChar}{$table}{$quoteChar} as {$quoteChar}{$alias}{$quoteChar}\n";

        // joins
        foreach ($this->joins as $join) {
            $sql .= $join->toSql()."\n";
        }

        // condition
        $condition = $this->condition->toSql();
        if (!is_null($condition)) {
            $sql .= "where $condition\n";
        }

        // orders
        if(count($this->orders) > 0){
            $sql .= 'order by ';
            foreach ($this->orders as $order) {
                $column = $order['column'];
                $type = $order['type'];

                $sql .= "$column $type, ";
            }

            $sql = rtrim($sql, ", ");
            $sql .= "\n";
        }

        // limit
        if (!is_null($this->limit)) {
            $offset = $this->limit['offset'];
            $limit = $this->limit['limit'];

            if($offset > 0){
                $sql .= "limit {$limit}, {$offset}";
            }else{
                $sql .= "limit {$limit}";
            }
        }

        $sql = rtrim($sql, "\n");

        return $sql;
    }