>
> initially I used Oracle adapter/statement code as a framework to create
> sql
> functionality, so 1.) might be true. I/Ralph will fix it.
>
I figured. I did the same, although I found myself scanning for differences
between the Oracle, MySQL, and MSSQL adapters in many cases to figure out
how to handle some of these things.
Juozas wrote:
>
> Checking options in 2.) might be possible, but not necessary needed :) I
> mean current approach will work with future sqlsrv_* improvements also,
> because we relay on that driver to check if options exist.
>
Perhaps not necessary, but could be beneficial. I just figured it would
improve performance since the adapter could either raise exceptions without
trying to connect to the server and waiting for an error response or else
simply ignore unsupported driver options preventing the error altogether. I
think I'd prefer the latter, simply because it would make it easier to
switch adapters.
Juozas wrote:
>
> Transactions functions throws exceptions because it seemed for me that
> errors in sql transactions are more dangerous than in other drivers
> (maybe).
> Returning false/true is different from abstract adapter so probably not
> good
> idea to use and user code shouldn't handle return in sqlsrv-specific way.
> That was my idea, but I might be wrong :)
>
I agree that this is consistent with the current implementation of the base
adapter class. When I coded my class, those functions returned a boolean, so
I just passed back the return values of the inner function call. I wouldn't
change anything; it's just a difference I noted.
Juozas wrote:
>
> Limit stuff is wid in sql server it self :) I have seen ways to do it in
> 2008-only (which are more elegant), but since this driver focuses on
> general
> case I chose to use good-old approach :) For a possible bug maybe you can
> create full test-case? That would be really helpful.
>
As I already replied to Ralph, the only variable here would be a SQL table
itself. (While trying this test case, I also discovered that limit() has no
effect unless you also explicitly apply an order. I don't know if that is a
caveat or a bug.)
Here is a "simple" test case.
SQL:
================
CREATE TABLE small_numbers (
N tinyint NOT NULL PRIMARY KEY CLUSTERED
)
GO
DECLARE @COUNTER tinyint
SET @COUNTER = 1
WHILE @COUNTER < 58 BEGIN
INSERT INTO small_numbers VALUES(@COUNTER)
SET @COUNTER = @COUNTER + 1
END
GO
GRANT SELECT ON small_numbers TO username
GO
INI:
===================
[LIMIT_TEST]
resources.db.adapter = "sqlsrv"
resources.db.params.host = "hostname"
resources.db.params.dbname = "database"
resources.db.params.username = "username"
resources.db.params.password = "password"
PHP:
===================
TestController.php
<?php
class TestController extends Zend_Controller_Action
{
public function limitAction()
{
$current_page = (int) $this->getRequest()->getUserParam('page', 1);
$config = new Zend_Config_Ini(APPLICATION_PATH .
'/configs/testconfig.ini');
$db = Zend_Db::factory($config->LIMIT_TEST->resources->db);
$select = $db->select()
->from('small_numbers')
->order('N');
$paginator = Zend_Paginator::factory($select);
$paginator->setItemCountPerPage(10);
$paginator->setCurrentPageNumber($current_page);
$this->view->paginator = $paginator;
}
}
limit.phtml
<html>
<body>
<h1>Example</h1>
<?php if (count($this->paginator)): ?>
<?php echo $this->paginationControl($this->paginator,
'All',
'test/my_pagination_control.phtml'); ?>
<ul>
<?php foreach ($this->paginator as $item): ?>
<li><?php echo $item['N']; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php echo $this->paginationControl($this->paginator,
'All',
'test/my_pagination_control.phtml'); ?>
</body>
</html>
my_pagination_control.phtml
<!--
See
http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
-->
<?php if ($this->pageCount): ?>
<div class="paginationControl">
<!-- Previous page link -->
<?php if (isset($this->previous)): ?>
"<?php echo $this- url(array('page' => $this->previous)); ?>">
< Previous
|
<?php else: ?>
< Previous |
<?php endif; ?>
<!-- Numbered page links -->
<?php foreach ($this->pagesInRange as $page): ?>
<?php if ($page != $this->current): ?>
"<?php echo $this- url(array('page' => $page)); ?>">
<?php echo $page; ?>
|
<?php else: ?>
<?php echo $page; ?> |
<?php endif; ?>
<?php endforeach; ?>
<!-- Next page link -->
<?php if (isset($this->next)): ?>
"<?php echo $this- url(array('page' => $this->next)); ?>">
Next >
<?php else: ?>
Next >
<?php endif; ?>
</div>
<?php endif; ?>
Juozas wrote:
>
> Lastinsertid was made with intention (again) to not to break abstract
> adapter. It works in all general cases and will only break in some "crazy"
> cases :) However, adapter can't decide tha and developer should know, that
> in complex queries it might break. As I said - it works in all normal
> cases
> and is tested with unit-tests :)
>
I'm not knocking it. The major differences in what you've done involve
caching the value in a protected member variable when applicable, and
allowing the method to query for the id for a specific table. Both of those
look useful.
Juozas wrote:
>
> Server version is a little bit tricky. We use
> http://msdn.microsoft.com/en-us/library/cc296165%28SQL.90%29.aspx to get
> version and we don't know actual server version - only client info is
> available. Are there sql queries to get actual server version and do we
> want
> to use it? It seemed for me that getServerVersion is used to check for
> driver/server version specific cases so driver version in this case is not
> a
> full bug :)
>
Actually there are, but there is also a native function in the driver itself
that returns an array containing that information: sqlsrv_server_info().
http://msdn.microsoft.com/en-us/library/cc296204%28SQL.90%29.aspx
I believe SQL 2000 returns 8.x, 2005 returns 9.x, and 2008 returns 10.x.
public function getServerVersion()
{
$this->_connect();
$info = sqlsrv_server_info($this->_connection);
if ($info) {
$version = $info['SQLServerVersion'];
}
return $version;
}
If it doesn't break compatibility too much, it would be nice to add a couple
methods like these:
/**
* Returns information about the connection and client stack. A
connection
* must be established before calling this function.
*
* @param string $key Optional.
* @return string|array
*/
public function getClientInfo($key = null)
{
if ($key !== null && !in_array($key, array('DriverDllName',
'DriverODBCVer', 'DriverVer', 'ExtensionVer'))) {
throw new Zend_Db_Adapter_Sqlsrv_Exception('Invalid key');
}
$this->_connect();
$info = sqlsrv_client_info($this->_connection);
if ($key !== null) {
return $info[$key];
}
return $info;
}
/**
* Returns information about the server. A connection must be
established
* before calling this function.
*
* @param string $key Optional
* @return string|array
*/
public function getServerInfo($key = null)
{
if ($key !== null && !in_array($key, array('CurrentDatabase',
'SQLServerVersion', 'SQLServerName'))) {
throw new Zend_Db_Adapter_Sqlsrv_Exception('Invalid key');
}
$this->_connect();
$info = sqlsrv_server_info($this->_connection);
if ($key !== null) {
return $info[$key];
}
return $info;
}
Juozas wrote:
>
> fetchArray is again work-around for abstract cases. Adapter wants to have
> ability to make columns lowercase,uppercase,default hence we need to loop
> through all keys and do it. Although keys are generated once per statement
> and this operation is not expensive so I don't think that is a problem.
> Correct me if I'm wrong :)
>
I don't know that it's a problem. As for case, I expect the case to match
that of the query. The only reason I asked was that I used the corresponding
native methods in my class whereas I noticed that this version did not.
Juozas wrote:
>
> Very good point about error messages ;) I'm definitely going to look at it
> and will probably change exception to store all errors and give access to
> first one/all/etc. It won't break anything just give addition options.
>
I'll admit even in my own implementation I didn't do this very well. I only
point this out because I have learned from experience that I could have done
it better and therefore would like to see a better implementation when this
is released.
Juozas wrote:
>
> This driver was created with an intention to have (as much as possible)
> transparent adapter - only a few unit-tests from abstract suite are marked
> as skipped (bind by name etc.) and all others work just fine.
>
I understand. The underlying driver does things differently than most of the
other drivers, and while I think those changes are particularly useful for
developing with SQL Server, they do present issues with providing a standard
API that allows easy switching from one adapter to another.
Andrew
--
View this message in context: http://www.nabble.com/Comments-on-Zend_Db_Adapter_Sqlsrv-tp24725644p24739585.html
Sent from the Zend DB mailing list archive at Nabble.com.
没有评论:
发表评论