- Merge with Mssql repository bugfix
This commit is contained in:
		
							parent
							
								
									724ab250ab
								
							
						
					
					
						commit
						e1990e7cc0
					
				| @ -92,16 +92,19 @@ class MsSQL implements AdapterInterface { | ||||
|         $parts[] = "Server={$this->server}" . ( isset($this->port) ? ",{$this->port}" : "" ); | ||||
|         $parts[] = "Database={$this->database}"; | ||||
|         $parts[] = "ConnectionPooling={$this->connectionPooling}"; | ||||
|          | ||||
| 
 | ||||
|         if ( $this->app ?? false ) { | ||||
|             $parts[] = "APP={$this->app}"; | ||||
|         } | ||||
|         | ||||
| 
 | ||||
|         if ( $this->encrypt ?? false ) { | ||||
|             $parts[] = "Encrypt=1"; | ||||
|         } | ||||
|         else { | ||||
|             $parts[] = "Encrypt=0"; | ||||
|         } | ||||
|          | ||||
| 	if ( $this->failoverPartner ?? false ) { | ||||
| 	    if ( $this->failoverPartner ?? false ) { | ||||
|             $parts[] = "Failover_Partner={$this->failoverPartner}"; | ||||
|         } | ||||
|          | ||||
| @ -130,7 +133,7 @@ class MsSQL implements AdapterInterface { | ||||
|         } | ||||
|          | ||||
|         if ( $this->trustServerCertificate ?? false ) { | ||||
|             $parts[] = "TrustServerCertificate=1"; | ||||
|             $parts[] = "TrustServerCertificate=yes"; | ||||
|         } | ||||
|          | ||||
|         if ( $this->WSID ?? false ) { | ||||
| @ -235,4 +238,8 @@ class MsSQL implements AdapterInterface { | ||||
|         return Repository\MssqlRepository::class; | ||||
|     } | ||||
| 
 | ||||
|     public function queryBuilderClass() : string | ||||
|     { | ||||
|         return QueryBuilder\MssqlQueryBuilder::class; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -137,4 +137,14 @@ class SQLite implements AdapterInterface { | ||||
|             'unsigned' => "", | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     public function repositoryClass() : string | ||||
|     { | ||||
|         return Repository\SqliteRepository::class; | ||||
|     } | ||||
| 
 | ||||
|     public function queryBuilderClass() : string | ||||
|     { | ||||
|         return QueryBuilder\SqliteQueryBuilder::class; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -44,6 +44,11 @@ class EntityCollection extends \ArrayObject { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function filtersArray(Callable $callback) : array | ||||
|     { | ||||
|         return $this->filtersCollection($callback, true, false)->toArray(); | ||||
|     } | ||||
| 
 | ||||
|     public function filtersOne(Callable $callback) : ? object | ||||
|     { | ||||
|         foreach($this->filters($callback, true) as $item) { | ||||
|  | ||||
| @ -204,6 +204,10 @@ trait EntityTrait { | ||||
|      */ | ||||
|     public function isLoaded() : bool | ||||
|     { | ||||
|         if (empty($this->entityLoadedDataset)) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         if ( null === $pkField = $this->resolveEntity()->getPrimaryKeyField($this) ) { | ||||
|             throw new Exception\EntityPrimaryKeyUnknown(sprintf("Entity %s has no field containing attributes 'primary_key'", static::class)); | ||||
|         } | ||||
| @ -315,7 +319,7 @@ trait EntityTrait { | ||||
|      */ | ||||
|     public static function field($name, ? string $alias = null) : EntityField | ||||
|     { | ||||
|         return new EntityField(static::class, $name, $alias ?: Repository::DEFAULT_ALIAS, Ulmus::resolveEntity(static::class)); | ||||
|         return new EntityField(static::class, $name, $alias ? Ulmus::repository(static::class)->adapter->adapter()->escapeIdentifier($alias, Adapter\AdapterInterface::IDENTIFIER_FIELD) : Repository::DEFAULT_ALIAS, Ulmus::resolveEntity(static::class)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -247,6 +247,10 @@ class QueryBuilder implements Query\QueryBuilderInterface | ||||
| 
 | ||||
|         $limit->set($value); | ||||
| 
 | ||||
|         if ($value === 0) { | ||||
|             $this->removeFragment(Query\Limit::class); | ||||
|         } | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -2,11 +2,9 @@ | ||||
| 
 | ||||
| namespace Ulmus\QueryBuilder; | ||||
| 
 | ||||
| use Ulmus\QueryBuilder; | ||||
| use Ulmus\{Query, QueryBuilder }; | ||||
| 
 | ||||
| use Ulmus\Query; | ||||
| 
 | ||||
| class MssqlQueryBuilder extends QueryBuilder implements Ulmus\Query\QueryBuilderInterface | ||||
| class MssqlQueryBuilder extends QueryBuilder implements Query\QueryBuilderInterface | ||||
| { | ||||
|     public function limit(int $value) : self | ||||
|     { | ||||
| @ -17,6 +15,10 @@ class MssqlQueryBuilder extends QueryBuilder implements Ulmus\Query\QueryBuilder | ||||
| 
 | ||||
|         $offset->limit = $value; | ||||
| 
 | ||||
|         if ($value === 0) { | ||||
|             $this->removeFragment(Query\MsSQL\Offset::class); | ||||
|         } | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -68,7 +68,7 @@ class Repository | ||||
| 
 | ||||
|     public function count() : int | ||||
|     { | ||||
|         $this->removeQueryFragment(Query\Select::class); | ||||
|         $this->removeQueryFragment([ Query\Select::class, Query\OrderBy::class,  ]); | ||||
| 
 | ||||
|         if ( $this->queryBuilder->getFragment(Query\GroupBy::class) ) { | ||||
|             $this->select( "DISTINCT COUNT(*) OVER ()" ); | ||||
| @ -149,16 +149,20 @@ class Repository | ||||
| 
 | ||||
|             $statement = $this->insertSqlQuery($fieldsAndValue ?? $dataset, $replace)->runInsertQuery(); | ||||
| 
 | ||||
|             if ( ( 0 !== $statement->lastInsertId ) && | ||||
|                 ( null !== $primaryKeyDefinition )) { | ||||
| 
 | ||||
|             if ( null !== $primaryKeyDefinition ) { | ||||
|                 $pkField = key($primaryKeyDefinition); | ||||
|                 $dataset[$pkField] = $statement->lastInsertId; | ||||
| 
 | ||||
|                 if ($statement->lastInsertId ) { | ||||
|                     $dataset[$pkField] = $statement->lastInsertId; | ||||
|                 } | ||||
|                 elseif ($replace) { | ||||
|                     $pkValue = $dataset[$pkField]; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             $entity->entityFillFromDataset($dataset, true); | ||||
| 
 | ||||
|             return (bool) $statement->lastInsertId; | ||||
|             return (bool) ($pkValue ?? $statement->lastInsertId); | ||||
|         } | ||||
|         else { | ||||
|             if ( $primaryKeyDefinition === null ) { | ||||
| @ -270,7 +274,7 @@ class Repository | ||||
|     { | ||||
|         $schema = $schema ?: $this->entityResolver->schemaName(); | ||||
| 
 | ||||
|         $this->queryBuilder->truncate($this->escapeTable($table ?: $this->entityResolver->tableName()), $alias ?: $this->alias, $this->escapedDatabase(), $schema ? $this->escapeSchema($schema) : null); | ||||
|         $this->queryBuilder->truncate($this->escapeTable($table ?: $this->entityResolver->tableName()), $this->escapeIdentifier($alias ?: $this->alias), $this->escapedDatabase(), $schema ? $this->escapeSchema($schema) : null); | ||||
| 
 | ||||
|         $this->finalizeQuery(); | ||||
| 
 | ||||
| @ -336,7 +340,7 @@ class Repository | ||||
| 
 | ||||
|         foreach ($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) { | ||||
|             if (null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], new RelationIgnore)) { | ||||
|                 $this->select("$alias.$key as {$prependField}{$field['name']}"); | ||||
|                 $this->select(sprintf("%s.$key as {$prependField}{$field['name']}", $this->escapeIdentifier($alias))); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -350,7 +354,7 @@ class Repository | ||||
|         foreach ($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) { | ||||
|             if (null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], new RelationIgnore)) { | ||||
|                 $fieldlist[] = $key; | ||||
|                 $fieldlist[] = $entity::field($field['name'], $alias); | ||||
|                 $fieldlist[] = $entity::field($field['name'], $this->escapeIdentifier($alias)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -380,7 +384,7 @@ class Repository | ||||
| 
 | ||||
|     public function insert(array $fieldlist, string $table, string $alias, ? string $schema, bool $replace = false) : self | ||||
|     { | ||||
|         $this->queryBuilder->insert($fieldlist, $this->escapeTable($table), $alias, $this->escapedDatabase(), $schema, $replace); | ||||
|         $this->queryBuilder->insert($fieldlist, $this->escapeTable($table), $this->escapeIdentifier($alias), $this->escapedDatabase(), $schema, $replace); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @ -394,7 +398,7 @@ class Repository | ||||
| 
 | ||||
|     public function update(string $table, string $alias, ? string $schema) : self | ||||
|     { | ||||
|         $this->queryBuilder->update($this->escapeTable($table), $alias, $this->escapedDatabase(), $schema); | ||||
|         $this->queryBuilder->update($this->escapeTable($table), $this->escapeIdentifier($alias), $this->escapedDatabase(), $schema); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @ -418,13 +422,13 @@ class Repository | ||||
| 
 | ||||
|     public function from(string $table, ? string $alias, ? string $schema) : self | ||||
|     { | ||||
|         $this->queryBuilder->from($this->escapeTable($table), $alias, $this->escapedDatabase(), $schema ? $this->escapeSchema($schema) : null); | ||||
|         $this->queryBuilder->from($this->escapeTable($table), $this->escapeIdentifier($alias), $this->escapedDatabase(), $schema ? $this->escapeSchema($schema) : null); | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function join(string $type, $table, $field, $value, ? string $alias = null, ? callable $callback = null) : self | ||||
|     { | ||||
|         $join = $this->queryBuilder->withJoin($type, $this->escapeTable($table), $field, $value, false, $alias); | ||||
|         $join = $this->queryBuilder->withJoin($type, $this->escapeTable($table), $field, $value, false, $this->escapeIdentifier($alias)); | ||||
| 
 | ||||
|         if ( $callback ) { | ||||
|             $callback($join); | ||||
| @ -435,7 +439,7 @@ class Repository | ||||
| 
 | ||||
|     public function outerJoin(string $type, $table, $field, $value, ? string $alias = null, ? callable $callback = null) : self | ||||
|     { | ||||
|         $join = $this->queryBuilder->withJoin($type, $this->escapeTable($table), $field, $value, true, $alias); | ||||
|         $join = $this->queryBuilder->withJoin($type, $this->escapeTable($table), $field, $value, true, $this->escapeIdentifier($alias)); | ||||
| 
 | ||||
|         if ( $callback ) { | ||||
|             $callback($join); | ||||
| @ -563,7 +567,9 @@ class Repository | ||||
| 
 | ||||
|                 foreach($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) { | ||||
|                     if ( null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], new RelationIgnore) ) { | ||||
|                         $this->select("$alias.$key as {$alias}\${$field['name']}"); | ||||
|                         $escAlias = $this->escapeIdentifier($alias); | ||||
| 
 | ||||
|                         $this->select("$escAlias.$key as $alias\${$field['name']}"); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
| @ -626,7 +632,7 @@ class Repository | ||||
|         } | ||||
| 
 | ||||
|         if ( null === $this->queryBuilder->getFragment(Query\Select::class) ) { | ||||
|             $this->select("{$this->alias}.*"); | ||||
|             $this->select($this->escapeIdentifier($this->alias) . ".*"); | ||||
|         } | ||||
| 
 | ||||
|         # Apply FILTER annotation to this too !
 | ||||
|  | ||||
| @ -7,6 +7,11 @@ use Ulmus\Annotation\Property\Field; | ||||
| 
 | ||||
| trait EscapeTrait | ||||
| { | ||||
|     public function escapeIdentifier(string $identifier) : string | ||||
|     { | ||||
|         return $this->escapeField($identifier); | ||||
|     } | ||||
| 
 | ||||
|     public function escapeField(string $identifier) : string | ||||
|     { | ||||
|         return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_FIELD); | ||||
|  | ||||
| @ -5,66 +5,11 @@ namespace Ulmus\Repository; | ||||
| use Ulmus\{Repository, Query, Ulmus, Common}; | ||||
| 
 | ||||
| class MssqlRepository extends Repository { | ||||
| /* | ||||
|     protected function finalizeQuery() : void | ||||
|     { | ||||
|         if ( null !== $offset = $this->queryBuilder->getFragment(Query\Offset::class) ) { | ||||
|             if ( null === $limit = $this->queryBuilder->getFragment(Query\Limit::class) ) { | ||||
|                 throw new \Exception("Your offset query fragment is missing a LIMIT value."); | ||||
|             } | ||||
| 
 | ||||
|             # an order by is mandatory for mssql offset/limit
 | ||||
|             if ( null === $order = $this->queryBuilder->getFragment(Query\OrderBy::class) ) { | ||||
|                 $this->orderBy("(SELECT 0)"); | ||||
|             }  | ||||
| 
 | ||||
|             $mssqlOffset = new \Ulmus\Query\MsSQL\Offset(); | ||||
| 
 | ||||
|             $mssqlOffset->set($offset->offset, $limit->limit); | ||||
| 
 | ||||
|             $this->queryBuilder->removeFragment($offset); | ||||
|             $this->queryBuilder->removeFragment($limit); | ||||
| 
 | ||||
|             $this->queryBuilder->push($mssqlOffset); | ||||
|         } | ||||
|         elseif ( null !== $limit = $this->queryBuilder->getFragment(Query\Limit::class) ) { | ||||
| 
 | ||||
|             if ( null !== $select = $this->queryBuilder->getFragment(Query\Select::class) ) { | ||||
|                 $select->top = $limit->limit; | ||||
|             } | ||||
|             elseif ( null !== $delete = $this->queryBuilder->getFragment(Query\Delete::class) ) { | ||||
|                 $delete->top = $limit->limit; | ||||
|             } | ||||
| 
 | ||||
|             $this->queryBuilder->removeFragment($limit); | ||||
|         } | ||||
|     } | ||||
| */ | ||||
| 
 | ||||
|     protected function finalizeQuery() : void | ||||
|     { | ||||
|         if ( null !== $offset = $this->queryBuilder->getFragment(Query\Offset::class) ) { | ||||
|             # an order by is mandatory for mssql offset/limit
 | ||||
|             if ( null === $order = $this->queryBuilder->getFragment(Query\OrderBy::class) ) { | ||||
|                 $this->orderBy("(SELECT 0)"); | ||||
|             } | ||||
| 
 | ||||
|             if ( empty ($offset->offset ) ) { | ||||
|                 if ( null !== $select = $this->queryBuilder->getFragment(Query\Select::class) ) { | ||||
|                     $select->top = $offset->limit; | ||||
|                 } | ||||
|                 elseif ( null !== $delete = $this->queryBuilder->getFragment(Query\Delete::class) ) { | ||||
|                     $delete->top = $offset->limit; | ||||
|                 } | ||||
|                 $this->queryBuilder->removeFragment($offset); | ||||
|             } | ||||
|             elseif ( empty($offset->limit) ) { | ||||
|                 throw new \Exception("Your offset query fragment is missing a LIMIT value."); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if ( null !== $limit = $this->queryBuilder->getFragment(Query\Limit::class) ) { | ||||
|             $this->queryBuilder->removeFragment($limit); | ||||
|         if ( null === $order = $this->queryBuilder->getFragment(Query\OrderBy::class) ) { | ||||
|             $this->orderBy("(SELECT 0)"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -47,9 +47,11 @@ class RelationBuilder | ||||
| 
 | ||||
|             return $this->resolveRelation($name) ?: $this->resolveVirtual($name); | ||||
|         } | ||||
|         else { | ||||
|             return $this->instanciateEmptyObject($name, $this->resolver->searchFieldAnnotation($name, new Relation() )); | ||||
|         elseif ( $relation = $this->resolver->searchFieldAnnotation($name, new Relation() ) ) { | ||||
|             return $this->instanciateEmptyObject($name, $relation); | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     protected function resolveVirtual(string $name) /* : bool|object|EntityCollection */ | ||||
|  | ||||
| @ -15,7 +15,17 @@ trait SearchRequestPaginationTrait { | ||||
|     public bool $skipCount = false; | ||||
| 
 | ||||
|     public ? array $columns = null; | ||||
|      | ||||
| 
 | ||||
|     public function count(): int | ||||
|     { | ||||
|         return $this->count; | ||||
|     } | ||||
| 
 | ||||
|     public function page(): int | ||||
|     { | ||||
|         return $this->page; | ||||
|     } | ||||
| 
 | ||||
|     public function limit(): int  | ||||
|     { | ||||
|         return $this->limit; | ||||
| @ -23,7 +33,7 @@ trait SearchRequestPaginationTrait { | ||||
| 
 | ||||
|     public function offset(): int  | ||||
|     { | ||||
|         return (int) ( abs( ( $this->page - 1 ) * $this->limit() ) ); | ||||
|         return (int) ( abs( ( $this->page() - 1 ) * $this->limit() ) ); | ||||
|     } | ||||
| 
 | ||||
|     public function pagination(int $page, int $itemCount) : void  | ||||
| @ -34,17 +44,25 @@ trait SearchRequestPaginationTrait { | ||||
|      | ||||
|     public function pageCount() : int | ||||
|     { | ||||
|         return ceil($this->count / $this->limit()); | ||||
|         return ceil($this->count() / $this->limit()); | ||||
|     } | ||||
|      | ||||
|     public function hasPagination() : int | ||||
|     { | ||||
|         return $this->pageCount() > 1; | ||||
|     } | ||||
| 
 | ||||
|     public function skipCount(bool $value) : self | ||||
|     { | ||||
|         $this->skipCount = $value; | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function resultShown() : int | ||||
|     { | ||||
|         $total = $this->page() * $this->limit(); | ||||
| 
 | ||||
|         return $total <= $this->count() ? $total : $this->count(); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user