public function insert($object, $meta=null)
    {
        $query = new Query\Insert;

        if (is_array($meta)) {
            throw new \BadMethodCallException("Please use insertTable()");
        }

        if ($meta) {
            $meta = !$meta instanceof Meta ? $this->mapper->getMeta($meta) : $meta;
        } else {
            $meta = $this->mapper->getMeta(get_class($object));
        }

        if (!$meta->canInsert) {
            throw new Exception("Meta {$meta->id} prohibits insert");
        }

        event_before: {
            if (isset($meta->on['beforeInsert'])) {
                foreach ($meta->on['beforeInsert'] as $cb) { $cb = [$object, $cb]; $cb(); }
            }
            if (isset($this->on['beforeInsert'])) {
                foreach ($this->on['beforeInsert'] as $cb) { $cb($object, $meta); }
            }
        }

        query: {
            $query->values = $this->mapper->mapObjectToRow($object, $meta, 'insert');
            if (!$query->table) {
                $query->table = $meta->table;
            }

            list ($sql, $params, $props) = $query->buildQuery($meta);
            $stmt = $this->getConnector()->prepare($sql);
            $stmt->execute($params);
        }
        
        $lastInsertId = null;

        // we need to be careful with "lastInsertId": SQLite generates one even without a PRIMARY
        if ($object && $meta->primary) {
            $lastInsertId = $this->getConnector()->lastInsertId();
            if ($lastInsertId && $meta->autoinc) {
                $field = $meta->fields[$meta->autoinc];
                $handler = $this->mapper->determineTypeHandler(Mapper::AUTOINC_TYPE);
                if (!$handler) {
                    throw new \UnexpectedValueException();
                }
                $meta->setValue($object, $meta->autoinc, $lastInsertId);
            }
        }
        
        event_after: {
            if (isset($meta->on['afterInsert'])) {
                foreach ($meta->on['afterInsert'] as $cb) { $cb = [$object, $cb]; $cb(); }
            }
            if (isset($this->on['afterInsert'])) {
                foreach ($this->on['afterInsert'] as $cb) { $cb($object, $meta); }
            }
        }

        return $lastInsertId;
    }