Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
bcd884ad
Commit
bcd884ad
authored
Dec 27, 2011
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
...
parent
d75d9326
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
248 additions
and
169 deletions
+248
-169
ColumnSchema.php
framework/db/dao/ColumnSchema.php
+1
-1
QueryBuilder.php
framework/db/dao/QueryBuilder.php
+247
-168
No files found.
framework/db/dao/ColumnSchema.php
View file @
bcd884ad
...
...
@@ -19,7 +19,7 @@ namespace yii\db\dao;
class
ColumnSchema
extends
\yii\base\Component
{
/**
* The followings are supported abstract column data types.
* The followings are
the
supported abstract column data types.
*/
const
TYPE_STRING
=
'string'
;
const
TYPE_TEXT
=
'text'
;
...
...
framework/db/dao/QueryBuilder.php
View file @
bcd884ad
...
...
@@ -34,7 +34,7 @@ class QueryBuilder extends \yii\base\Object
*/
public
$connection
;
/**
* @var Driver the database driver
* @var Driver the database driver
used for this query builder.
*/
public
$driver
;
/**
...
...
@@ -43,9 +43,10 @@ class QueryBuilder extends \yii\base\Object
*/
public
$separator
=
" "
;
/**
* @var Query the Query object. This is set when calling [[build()]] to generate a non-SELECT SQL statement.
* @var Query the Query object that is currently processed by the query builder to generate a SQL statement.
* After the SQL statement is generated by [[build()]], this property will be set null.
*/
p
rivate
$_
query
;
p
ublic
$
query
;
/**
* Constructor.
...
...
@@ -66,33 +67,43 @@ class QueryBuilder extends \yii\base\Object
*/
public
function
build
(
$query
)
{
$this
->
query
=
$query
;
if
(
$query
->
operation
!==
null
)
{
// non-SELECT query
$this
->
_query
=
$query
;
$method
=
array_shift
(
$query
->
operation
);
$sql
=
call_user_func_array
(
array
(
$this
,
$method
),
$query
->
operation
);
$this
->
_query
=
null
;
return
$sql
;
}
else
{
// SELECT query
$clauses
=
array
(
$this
->
buildSelect
(
$query
),
$this
->
buildFrom
(
$query
),
$this
->
buildJoin
(
$query
),
$this
->
buildWhere
(
$query
),
$this
->
buildGroupBy
(
$query
),
$this
->
buildHaving
(
$query
),
$this
->
buildUnion
(
$query
),
$this
->
buildOrderBy
(
$query
),
$this
->
buildLimit
(
$query
),
$this
->
buildSelect
(),
$this
->
buildFrom
(),
$this
->
buildJoin
(),
$this
->
buildWhere
(),
$this
->
buildGroupBy
(),
$this
->
buildHaving
(),
$this
->
buildUnion
(),
$this
->
buildOrderBy
(),
$this
->
buildLimit
(),
);
return
implode
(
$this
->
separator
,
array_filter
(
$clauses
));
$sql
=
implode
(
$this
->
separator
,
array_filter
(
$clauses
));
}
$this
->
query
=
null
;
return
$sql
;
}
/**
* Creates and executes an INSERT SQL statement.
* The method will properly escape the column names, and bind the values to be inserted.
* For example,
*
* ~~~
* $params = array();
* $sql = $queryBuilder->insert('tbl_user', array(
* 'name' => 'Sam',
* 'age' => 30,
* ), $params);
* ~~~
*
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name=>value) to be inserted into the table.
* @param array $params the parameters to be bound to the query. This method will modify
...
...
@@ -117,8 +128,8 @@ class QueryBuilder extends \yii\base\Object
$count
++
;
}
}
if
(
$this
->
_
query
instanceof
Query
)
{
$this
->
_
query
->
addParams
(
$params
);
if
(
$this
->
query
instanceof
Query
)
{
$this
->
query
->
addParams
(
$params
);
}
return
'INSERT INTO '
.
$this
->
driver
->
quoteTableName
(
$table
)
...
...
@@ -129,6 +140,15 @@ class QueryBuilder extends \yii\base\Object
/**
* Creates and executes an UPDATE SQL statement.
* The method will properly escape the column names and bind the values to be updated.
* For example,
*
* ~~~
* $params = array();
* $sql = $queryBuilder->update('tbl_user', array(
* 'status' => 1,
* ), 'age > 30', $params);
* ~~~
*
* @param string $table the table to be updated.
* @param array $columns the column data (name=>value) to be updated.
* @param mixed $condition the condition that will be put in the WHERE part. Please
...
...
@@ -153,8 +173,8 @@ class QueryBuilder extends \yii\base\Object
$count
++
;
}
}
if
(
$this
->
_
query
instanceof
Query
)
{
$this
->
_
query
->
addParams
(
$params
);
if
(
$this
->
query
instanceof
Query
)
{
$this
->
query
->
addParams
(
$params
);
}
$sql
=
'UPDATE '
.
$this
->
driver
->
quoteTableName
(
$table
)
.
' SET '
.
implode
(
', '
,
$lines
);
if
((
$where
=
$this
->
buildCondition
(
$condition
))
!=
''
)
{
...
...
@@ -166,6 +186,12 @@ class QueryBuilder extends \yii\base\Object
/**
* Creates and executes a DELETE SQL statement.
* For example,
*
* ~~~
* $sql = $queryBuilder->delete('tbl_user', 'status = 0');
* ~~~
*
* @param string $table the table where the data will be deleted from.
* @param mixed $condition the condition that will be put in the WHERE part. Please
* refer to [[Query::where()]] on how to specify condition.
...
...
@@ -191,6 +217,16 @@ class QueryBuilder extends \yii\base\Object
* If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly
* inserted into the generated SQL.
*
* For example,
*
* ~~~
* $sql = $queryBuilder->createTable('tbl_user', array(
* 'id' => 'pk',
* 'name' => 'string',
* 'age' => 'integer',
* ));
* ~~~
*
* @param string $table the name of the table to be created. The name will be properly quoted by the method.
* @param array $columns the columns (name=>definition) in the new table.
* @param string $options additional SQL fragment that will be appended to the generated SQL.
...
...
@@ -201,7 +237,7 @@ class QueryBuilder extends \yii\base\Object
$cols
=
array
();
foreach
(
$columns
as
$name
=>
$type
)
{
if
(
is_string
(
$name
))
{
$cols
[]
=
"
\t
"
.
$this
->
driver
->
quoteColumnName
(
$name
)
.
' '
.
$this
->
driver
->
getColumnType
(
$type
);
$cols
[]
=
"
\t
"
.
$this
->
driver
->
quoteColumnName
(
$name
)
.
' '
.
$this
->
getColumnType
(
$type
);
}
else
{
$cols
[]
=
"
\t
"
.
$type
;
...
...
@@ -213,13 +249,13 @@ class QueryBuilder extends \yii\base\Object
/**
* Builds a SQL statement for renaming a DB table.
* @param string $
tabl
e the table to be renamed. The name will be properly quoted by the method.
* @param string $
oldNam
e the table to be renamed. The name will be properly quoted by the method.
* @param string $newName the new table name. The name will be properly quoted by the method.
* @return string the SQL statement for renaming a DB table.
*/
public
function
renameTable
(
$
tabl
e
,
$newName
)
public
function
renameTable
(
$
oldNam
e
,
$newName
)
{
return
'RENAME TABLE '
.
$this
->
driver
->
quoteTableName
(
$
tabl
e
)
.
' TO '
.
$this
->
driver
->
quoteTableName
(
$newName
);
return
'RENAME TABLE '
.
$this
->
driver
->
quoteTableName
(
$
oldNam
e
)
.
' TO '
.
$this
->
driver
->
quoteTableName
(
$newName
);
}
/**
...
...
@@ -288,9 +324,10 @@ class QueryBuilder extends \yii\base\Object
* Builds a SQL statement for changing the definition of a column.
* @param string $table the table whose column is to be changed. The table name will be properly quoted by the method.
* @param string $column the name of the column to be changed. The name will be properly quoted by the method.
* @param string $type the new column type. The [[getColumnType]] method will be invoked to convert abstract column type (if any)
* into the physical one. Anything that is not recognized as abstract type will be kept in the generated SQL.
* For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become 'varchar(255) not null'.
* @param string $type the new column type. The [[getColumnType()]] method will be invoked to convert abstract
* column type (if any) into the physical one. Anything that is not recognized as abstract type will be kept
* in the generated SQL. For example, 'string' will be turned into 'varchar(255)', while 'string not null'
* will become 'varchar(255) not null'.
* @return string the SQL statement for changing the definition of a column.
*/
public
function
alterColumn
(
$table
,
$column
,
$type
)
...
...
@@ -306,20 +343,26 @@ class QueryBuilder extends \yii\base\Object
* The method will properly quote the table and column names.
* @param string $name the name of the foreign key constraint.
* @param string $table the table that the foreign key constraint will be added to.
* @param string $columns the name of the column to that the constraint will be added on. If there are multiple columns, separate them with commas.
* @param string|array $columns the name of the column to that the constraint will be added on.
* If there are multiple columns, separate them with commas or use an array to represent them.
* @param string $refTable the table that the foreign key references to.
* @param string $refColumns the name of the column that the foreign key references to. If there are multiple columns, separate them with commas.
* @param string|array $refColumns the name of the column that the foreign key references to.
* If there are multiple columns, separate them with commas or use an array to represent them.
* @param string $delete the ON DELETE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
* @param string $update the ON UPDATE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
* @return string the SQL statement for adding a foreign key constraint to an existing table.
*/
public
function
addForeignKey
(
$name
,
$table
,
$columns
,
$refTable
,
$refColumns
,
$delete
=
null
,
$update
=
null
)
{
if
(
!
is_array
(
$columns
))
{
$columns
=
preg_split
(
'/\s*,\s*/'
,
$columns
,
-
1
,
PREG_SPLIT_NO_EMPTY
);
}
foreach
(
$columns
as
$i
=>
$col
)
{
$columns
[
$i
]
=
$this
->
driver
->
quoteColumnName
(
$col
);
}
if
(
!
is_array
(
$refColumns
))
{
$refColumns
=
preg_split
(
'/\s*,\s*/'
,
$refColumns
,
-
1
,
PREG_SPLIT_NO_EMPTY
);
}
foreach
(
$refColumns
as
$i
=>
$col
)
{
$refColumns
[
$i
]
=
$this
->
driver
->
quoteColumnName
(
$col
);
}
...
...
@@ -353,27 +396,27 @@ class QueryBuilder extends \yii\base\Object
* Builds a SQL statement for creating a new index.
* @param string $name the name of the index. The name will be properly quoted by the method.
* @param string $table the table that the new index will be created for. The table name will be properly quoted by the method.
* @param string $column the column(s) that should be included in the index. If there are multiple columns, please separate them
* by commas. Each column name will be properly quoted by the method, unless a parenthesis is found in the name.
* @param string|array $columns the column(s) that should be included in the index. If there are multiple columns,
* separate them with commas or use an array to represent them. Each column name will be properly quoted
* by the method, unless a parenthesis is found in the name.
* @param boolean $unique whether to add UNIQUE constraint on the created index.
* @return string the SQL statement for creating a new index.
*/
public
function
createIndex
(
$name
,
$table
,
$column
,
$unique
=
false
)
{
$cols
=
array
();
$columns
=
preg_split
(
'/\s*,\s*/'
,
$column
,
-
1
,
PREG_SPLIT_NO_EMPTY
);
foreach
(
$columns
as
$col
)
public
function
createIndex
(
$name
,
$table
,
$columns
,
$unique
=
false
)
{
if
(
strpos
(
$col
,
'('
)
!==
false
)
{
$cols
[]
=
$col
;
}
else
{
$cols
[]
=
$this
->
driver
->
quoteColumnName
(
$col
);
if
(
!
is_array
(
$columns
))
{
$columns
=
preg_split
(
'/\s*,\s*/'
,
$columns
,
-
1
,
PREG_SPLIT_NO_EMPTY
);
}
foreach
(
$columns
as
$i
=>
$column
)
{
if
(
strpos
(
$column
,
'('
)
!==
false
)
{
$columns
[
$i
]
=
$column
;
}
else
{
$columns
[
$i
]
=
$this
->
driver
->
quoteColumnName
(
$column
);
}
}
return
(
$unique
?
'CREATE UNIQUE INDEX '
:
'CREATE INDEX '
)
.
$this
->
driver
->
quoteTableName
(
$name
)
.
' ON '
.
$this
->
driver
->
quoteTableName
(
$table
)
.
' ('
.
implode
(
', '
,
$cols
)
.
')'
;
.
$this
->
driver
->
quoteTableName
(
$table
)
.
' ('
.
implode
(
', '
,
$col
umn
s
)
.
')'
;
}
/**
...
...
@@ -391,7 +434,7 @@ class QueryBuilder extends \yii\base\Object
* Resets the sequence value of a table's primary key.
* The sequence will be reset such that the primary key of the next new row inserted
* will have the specified value or 1.
* @param
CDbTableSchema
$table the table schema whose primary key sequence will be reset
* @param
string
$table the table schema whose primary key sequence will be reset
* @param mixed $value the value for the primary key of the next new row inserted. If this is not set,
* the next new row's primary key will have a value 1.
*/
...
...
@@ -411,26 +454,30 @@ class QueryBuilder extends \yii\base\Object
/**
* Converts an abstract column type into a physical column type.
* The conversion is done using the type map specified in [[typeMap]].
* The
se abstract column types are supported (using MySQL as
example to explain the corresponding
* The
following abstract column types are supported (using MySQL as an
example to explain the corresponding
* physical types):
* <ul>
* <li>pk: an auto-incremental primary key type, will be converted into "int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY"</li>
* <li>string: string type, will be converted into "varchar(255)"</li>
* <li>text: a long string type, will be converted into "text"</li>
* <li>integer: integer type, will be converted into "int(11)"</li>
* <li>boolean: boolean type, will be converted into "tinyint(1)"</li>
* <li>float: float number type, will be converted into "float"</li>
* <li>decimal: decimal number type, will be converted into "decimal"</li>
* <li>datetime: datetime type, will be converted into "datetime"</li>
* <li>timestamp: timestamp type, will be converted into "timestamp"</li>
* <li>time: time type, will be converted into "time"</li>
* <li>date: date type, will be converted into "date"</li>
* <li>binary: binary data type, will be converted into "blob"</li>
* </ul>
*
* - `pk`: an auto-incremental primary key type, will be converted into "int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY"
* - `string`: string type, will be converted into "varchar(255)"
* - `text`: a long string type, will be converted into "text"
* - `smallint`: a small integer type, will be converted into "smallint(6)"
* - `integer`: integer type, will be converted into "int(11)"
* - `bigint`: a big integer type, will be converted into "bigint(20)"
* - `boolean`: boolean type, will be converted into "tinyint(1)"
* - `float``: float number type, will be converted into "float"
* - `decimal`: decimal number type, will be converted into "decimal"
* - `datetime`: datetime type, will be converted into "datetime"
* - `timestamp`: timestamp type, will be converted into "timestamp"
* - `time`: time type, will be converted into "time"
* - `date`: date type, will be converted into "date"
* - `money`: money type, will be converted into "decimal(19,4)"
* - `binary`: binary data type, will be converted into "blob"
*
* If the abstract type contains two or more parts separated by spaces (e.g. "string NOT NULL"), then only
* the first part will be converted, and the rest of the parts will be appended to the conver
sion
result.
* the first part will be converted, and the rest of the parts will be appended to the conver
ted
result.
* For example, 'string NOT NULL' is converted to 'varchar(255) NOT NULL'.
*
* If a type cannot be found in [[typeMap]], it will be returned without any change.
* @param string $type abstract column type
* @return string physical column type.
*/
...
...
@@ -438,22 +485,109 @@ class QueryBuilder extends \yii\base\Object
{
if
(
isset
(
$this
->
typeMap
[
$type
]))
{
return
$this
->
typeMap
[
$type
];
}
elseif
((
$pos
=
strpos
(
$type
,
' '
))
!==
false
)
{
$t
=
substr
(
$type
,
0
,
$pos
);
return
(
isset
(
$this
->
typeMap
[
$t
])
?
$this
->
typeMap
[
$t
]
:
$t
)
.
substr
(
$type
,
$pos
);
}
else
{
}
elseif
(
preg_match
(
'/^(\w+)\s+/'
,
$type
,
$matches
))
{
if
(
isset
(
$this
->
typeMap
[
$matches
[
0
]]))
{
return
preg_replace
(
'/^\w+/'
,
$this
->
typeMap
[
$matches
[
0
]],
$type
);
}
}
return
$type
;
}
/**
* Generates a SQL condition from the given PHP representation.
* @param string|array $condition the PHP representation of the SQL condition
* @return string the generated SQL condition.
*/
public
function
buildCondition
(
$condition
)
{
if
(
!
is_array
(
$condition
))
{
return
$condition
;
}
elseif
(
$condition
===
array
())
{
return
''
;
}
$n
=
count
(
$condition
);
$operator
=
strtoupper
(
$condition
[
0
]);
if
(
$operator
===
'OR'
||
$operator
===
'AND'
)
{
$parts
=
array
();
for
(
$i
=
1
;
$i
<
$n
;
++
$i
)
{
$part
=
$this
->
buildCondition
(
$condition
[
$i
]);
if
(
$part
!==
''
)
{
$parts
[]
=
'('
.
$part
.
')'
;
}
}
return
$parts
===
array
()
?
''
:
implode
(
' '
.
$operator
.
' '
,
$parts
);
}
if
(
!
isset
(
$condition
[
1
],
$condition
[
2
]))
{
throw
new
Exception
(
"Operator
$operator
requires at least two operands."
);
}
$column
=
$condition
[
1
];
if
(
strpos
(
$column
,
'('
)
===
false
)
{
$column
=
$this
->
connection
->
quoteColumnName
(
$column
);
}
if
(
$operator
===
'BETWEEN'
||
$operator
===
'NOT BETWEEN'
)
{
if
(
!
isset
(
$condition
[
3
]))
{
throw
new
Exception
(
"Operator
$operator
requires three operands."
);
}
$value1
=
is_string
(
$condition
[
2
])
?
$this
->
connection
->
quoteValue
(
$condition
[
2
])
:
(
string
)
$condition
[
2
];
$value2
=
is_string
(
$condition
[
3
])
?
$this
->
connection
->
quoteValue
(
$condition
[
3
])
:
(
string
)
$condition
[
3
];
return
"
$column
$operator
$value1
AND
$value2
"
;
}
$values
=
$condition
[
2
];
if
(
!
is_array
(
$values
))
{
$values
=
array
(
$values
);
}
if
(
$operator
===
'IN'
||
$operator
===
'NOT IN'
)
{
if
(
$values
===
array
())
{
return
$operator
===
'IN'
?
'0=1'
:
''
;
}
foreach
(
$values
as
$i
=>
$value
)
{
if
(
is_string
(
$value
))
{
$values
[
$i
]
=
$this
->
connection
->
quoteValue
(
$value
);
}
else
{
$values
[
$i
]
=
(
string
)
$value
;
}
}
return
$column
.
' '
.
$operator
.
' ('
.
implode
(
', '
,
$values
)
.
')'
;
}
if
(
$operator
===
'LIKE'
||
$operator
===
'NOT LIKE'
||
$operator
===
'OR LIKE'
||
$operator
===
'OR NOT LIKE'
)
{
if
(
$values
===
array
())
{
return
$operator
===
'LIKE'
||
$operator
===
'OR LIKE'
?
'0=1'
:
''
;
}
if
(
$operator
===
'LIKE'
||
$operator
===
'NOT LIKE'
)
{
$andor
=
' AND '
;
}
else
{
$andor
=
' OR '
;
$operator
=
$operator
===
'OR LIKE'
?
'LIKE'
:
'NOT LIKE'
;
}
$expressions
=
array
();
foreach
(
$values
as
$value
)
{
$expressions
[]
=
$column
.
' '
.
$operator
.
' '
.
$this
->
connection
->
quoteValue
(
$value
);
}
return
implode
(
$andor
,
$expressions
);
}
protected
function
buildSelect
(
$query
)
throw
new
Exception
(
'Unknown operator: '
.
$operator
);
}
/**
* @return string the SELECT clause built from [[query]].
*/
protected
function
buildSelect
()
{
$select
=
$query
->
distinct
?
'SELECT DISTINCT'
:
'SELECT'
;
if
(
$query
->
selectOption
!=
''
)
{
$select
.=
' '
.
$query
->
selectOption
;
$select
=
$
this
->
query
->
distinct
?
'SELECT DISTINCT'
:
'SELECT'
;
if
(
$
this
->
query
->
selectOption
!=
''
)
{
$select
.=
' '
.
$
this
->
query
->
selectOption
;
}
$columns
=
$query
->
select
;
$columns
=
$
this
->
query
->
select
;
if
(
empty
(
$columns
))
{
return
$select
.
' *'
;
}
...
...
@@ -480,13 +614,16 @@ class QueryBuilder extends \yii\base\Object
return
$select
.
' '
.
implode
(
', '
,
$columns
);
}
protected
function
buildFrom
(
$query
)
/**
* @return string the FROM clause built from [[query]].
*/
protected
function
buildFrom
()
{
if
(
empty
(
$query
->
from
))
{
if
(
empty
(
$
this
->
query
->
from
))
{
return
''
;
}
$tables
=
$query
->
from
;
$tables
=
$
this
->
query
->
from
;
if
(
is_string
(
$tables
)
&&
strpos
(
$tables
,
'('
)
!==
false
)
{
return
'FROM '
.
$tables
;
}
...
...
@@ -507,9 +644,12 @@ class QueryBuilder extends \yii\base\Object
return
'FROM '
.
implode
(
', '
,
$tables
);
}
protected
function
buildJoin
(
$query
)
/**
* @return string the JOIN clause built from [[query]].
*/
protected
function
buildJoin
()
{
$joins
=
$query
->
join
;
$joins
=
$
this
->
query
->
join
;
if
(
empty
(
$joins
))
{
return
''
;
}
...
...
@@ -533,7 +673,7 @@ class QueryBuilder extends \yii\base\Object
$joins
[
$i
]
.=
' ON '
.
$this
->
buildCondition
(
$join
[
2
]);
}
}
else
{
throw
new
Exception
(
'
The join clause may
be specified as an array of at least two elements.'
);
throw
new
Exception
(
'
A join clause must
be specified as an array of at least two elements.'
);
}
}
}
...
...
@@ -541,15 +681,21 @@ class QueryBuilder extends \yii\base\Object
return
implode
(
"
\n
"
,
$joins
);
}
protected
function
buildWhere
(
$query
)
/**
* @return string the WHERE clause built from [[query]].
*/
protected
function
buildWhere
()
{
$where
=
$this
->
buildCondition
(
$query
->
where
);
$where
=
$this
->
buildCondition
(
$
this
->
query
->
where
);
return
empty
(
$where
)
?
''
:
'WHERE '
.
$where
;
}
protected
function
buildGroupBy
(
$query
)
/**
* @return string the GROUP BY clause built from [[query]].
*/
protected
function
buildGroupBy
()
{
$columns
=
$query
->
groupBy
;
$columns
=
$
this
->
query
->
groupBy
;
if
(
empty
(
$columns
))
{
return
''
;
}
...
...
@@ -570,15 +716,21 @@ class QueryBuilder extends \yii\base\Object
return
'GROUP BY '
.
implode
(
', '
,
$columns
);
}
protected
function
buildHaving
(
$query
)
/**
* @return string the HAVING clause built from [[query]].
*/
protected
function
buildHaving
()
{
$having
=
$this
->
buildCondition
(
$query
->
having
);
$having
=
$this
->
buildCondition
(
$
this
->
query
->
having
);
return
empty
(
$having
)
?
''
:
'HAVING '
.
$having
;
}
protected
function
buildOrderBy
(
$query
)
/**
* @return string the ORDER BY clause built from [[query]].
*/
protected
function
buildOrderBy
()
{
$columns
=
$query
->
orderBy
;
$columns
=
$
this
->
query
->
orderBy
;
if
(
empty
(
$columns
))
{
return
''
;
}
...
...
@@ -603,21 +755,27 @@ class QueryBuilder extends \yii\base\Object
return
'ORDER BY '
.
implode
(
', '
,
$columns
);
}
protected
function
buildLimit
(
$query
)
/**
* @return string the LIMIT and OFFSET clauses built from [[query]].
*/
protected
function
buildLimit
()
{
$sql
=
''
;
if
(
$
query
->
limit
!==
null
&&
$
query
->
limit
>=
0
)
{
$sql
=
'LIMIT '
.
(
int
)
$query
->
limit
;
if
(
$
this
->
query
->
limit
!==
null
&&
$this
->
query
->
limit
>=
0
)
{
$sql
=
'LIMIT '
.
(
int
)
$
this
->
query
->
limit
;
}
if
(
$query
->
offset
>
0
)
{
$sql
.=
' OFFSET '
.
(
int
)
$query
->
offset
;
if
(
$
this
->
query
->
offset
>
0
)
{
$sql
.=
' OFFSET '
.
(
int
)
$
this
->
query
->
offset
;
}
return
ltrim
(
$sql
);
}
protected
function
buildUnion
(
$query
)
/**
* @return string the UNION clause built from [[query]].
*/
protected
function
buildUnion
()
{
$unions
=
$query
->
union
;
$unions
=
$
this
->
query
->
union
;
if
(
empty
(
$unions
))
{
return
''
;
}
...
...
@@ -631,83 +789,4 @@ class QueryBuilder extends \yii\base\Object
}
return
"UNION (
\n
"
.
implode
(
"
\n
) UNION (
\n
"
,
$unions
)
.
"
\n
)"
;
}
protected
function
buildCondition
(
$condition
)
{
if
(
!
is_array
(
$condition
))
{
return
$condition
;
}
elseif
(
$condition
===
array
())
{
return
''
;
}
$n
=
count
(
$condition
);
$operator
=
strtoupper
(
$condition
[
0
]);
if
(
$operator
===
'OR'
||
$operator
===
'AND'
)
{
$parts
=
array
();
for
(
$i
=
1
;
$i
<
$n
;
++
$i
)
{
$part
=
$this
->
buildCondition
(
$condition
[
$i
]);
if
(
$part
!==
''
)
{
$parts
[]
=
'('
.
$part
.
')'
;
}
}
return
$parts
===
array
()
?
''
:
implode
(
' '
.
$operator
.
' '
,
$parts
);
}
if
(
!
isset
(
$condition
[
1
],
$condition
[
2
]))
{
throw
new
Exception
(
"Operator
$operator
requires at least two operands."
);
}
$column
=
$condition
[
1
];
if
(
strpos
(
$column
,
'('
)
===
false
)
{
$column
=
$this
->
connection
->
quoteColumnName
(
$column
);
}
if
(
$operator
===
'BETWEEN'
||
$operator
===
'NOT BETWEEN'
)
{
if
(
!
isset
(
$condition
[
3
]))
{
throw
new
Exception
(
"Operator
$operator
requires three operands."
);
}
$value1
=
is_string
(
$condition
[
2
])
?
$this
->
connection
->
quoteValue
(
$condition
[
2
])
:
(
string
)
$condition
[
2
];
$value2
=
is_string
(
$condition
[
3
])
?
$this
->
connection
->
quoteValue
(
$condition
[
3
])
:
(
string
)
$condition
[
3
];
return
"
$column
$operator
$value1
AND
$value2
"
;
}
$values
=
$condition
[
2
];
if
(
!
is_array
(
$values
))
{
$values
=
array
(
$values
);
}
if
(
$operator
===
'IN'
||
$operator
===
'NOT IN'
)
{
if
(
$values
===
array
())
{
return
$operator
===
'IN'
?
'0=1'
:
''
;
}
foreach
(
$values
as
$i
=>
$value
)
{
if
(
is_string
(
$value
))
{
$values
[
$i
]
=
$this
->
connection
->
quoteValue
(
$value
);
}
else
{
$values
[
$i
]
=
(
string
)
$value
;
}
}
return
$column
.
' '
.
$operator
.
' ('
.
implode
(
', '
,
$values
)
.
')'
;
}
if
(
$operator
===
'LIKE'
||
$operator
===
'NOT LIKE'
||
$operator
===
'OR LIKE'
||
$operator
===
'OR NOT LIKE'
)
{
if
(
$values
===
array
())
{
return
$operator
===
'LIKE'
||
$operator
===
'OR LIKE'
?
'0=1'
:
''
;
}
if
(
$operator
===
'LIKE'
||
$operator
===
'NOT LIKE'
)
{
$andor
=
' AND '
;
}
else
{
$andor
=
' OR '
;
$operator
=
$operator
===
'OR LIKE'
?
'LIKE'
:
'NOT LIKE'
;
}
$expressions
=
array
();
foreach
(
$values
as
$value
)
{
$expressions
[]
=
$column
.
' '
.
$operator
.
' '
.
$this
->
connection
->
quoteValue
(
$value
);
}
return
implode
(
$andor
,
$expressions
);
}
throw
new
Exception
(
'Unknown operator: '
.
$operator
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment