Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
Practical-Cryptdb
Project
Project
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
Zhaozhen
Practical-Cryptdb
Commits
c4267e97
Commit
c4267e97
authored
Jan 17, 2018
by
yiwenshao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more fine grained sp_next
parent
417c895b
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
579 additions
and
498 deletions
+579
-498
load.cc
debug/load.cc
+33
-38
store.cc
debug/store.cc
+69
-5
store.hh
debug/store.hh
+0
-282
try_select_back.cc
debug/try_select_back.cc
+443
-0
try_select_data.cc
debug/try_select_data.cc
+34
-173
No files found.
debug/load.cc
View file @
c4267e97
...
...
@@ -28,6 +28,39 @@ static std::map<std::string, WrapperState*> clients;
Connect
*
globalConn
;
/*for each field, convert the format to FieldMeta_Wrapper*/
static
void
construct_insert
(
rawMySQLReturnValue
&
str
,
std
::
string
table
,
std
::
vector
<
std
::
string
>
&
res
){
std
::
string
head
=
string
(
"INSERT INTO `"
)
+
table
+
"` VALUES "
;
int
cnt
=
0
;
string
cur
=
head
;
for
(
unsigned
int
i
=
0u
;
i
<
str
.
rowValues
.
size
();
i
++
){
++
cnt
;
cur
+=
"("
;
for
(
unsigned
int
j
=
0u
;
j
<
str
.
rowValues
[
i
].
size
();
j
++
){
if
(
IS_NUM
(
str
.
fieldTypes
[
j
]))
{
cur
+=
str
.
rowValues
[
i
][
j
]
+=
","
;
}
else
{
int
len
=
str
.
rowValues
[
i
][
j
].
size
();
mysql_real_escape_string
(
globalConn
->
get_conn
(),
globalEsp
,
str
.
rowValues
[
i
][
j
].
c_str
(),
len
);
cur
+=
string
(
"
\"
"
)
+=
string
(
globalEsp
)
+=
"
\"
,"
;
}
}
cur
.
back
()
=
')'
;
cur
+=
","
;
if
(
cnt
==
num_of_pipe
){
cnt
=
0
;
cur
.
back
()
=
';'
;
res
.
push_back
(
cur
);
cur
=
head
;
}
}
if
(
cnt
!=
0
){
cur
.
back
()
=
';'
;
res
.
push_back
(
cur
);
}
}
static
void
init
(){
std
::
string
client
=
"192.168.1.1:1234"
;
...
...
@@ -137,43 +170,6 @@ static void load_string(string filename, vector<string> &res,unsigned long lengt
close
(
fd
);
}
static
void
construct_insert
(
rawMySQLReturnValue
&
str
,
std
::
string
table
,
std
::
vector
<
std
::
string
>
&
res
){
std
::
string
head
=
string
(
"INSERT INTO `"
)
+
table
+
"` VALUES "
;
int
cnt
=
0
;
string
cur
=
head
;
for
(
unsigned
int
i
=
0u
;
i
<
str
.
rowValues
.
size
();
i
++
){
++
cnt
;
cur
+=
"("
;
for
(
unsigned
int
j
=
0u
;
j
<
str
.
rowValues
[
i
].
size
();
j
++
){
if
(
IS_NUM
(
str
.
fieldTypes
[
j
]))
{
cur
+=
str
.
rowValues
[
i
][
j
]
+=
","
;
}
else
{
int
len
=
str
.
rowValues
[
i
][
j
].
size
();
mysql_real_escape_string
(
globalConn
->
get_conn
(),
globalEsp
,
str
.
rowValues
[
i
][
j
].
c_str
(),
len
);
cur
+=
string
(
"
\"
"
)
+=
string
(
globalEsp
)
+=
"
\"
,"
;
}
}
cur
.
back
()
=
')'
;
cur
+=
","
;
if
(
cnt
==
num_of_pipe
){
cnt
=
0
;
cur
.
back
()
=
';'
;
res
.
push_back
(
cur
);
cur
=
head
;
}
}
if
(
cnt
!=
0
){
cur
.
back
()
=
';'
;
res
.
push_back
(
cur
);
}
}
template
<
class
T
>
vector
<
T
>
flat_vec
(
vector
<
vector
<
T
>>
&
input
){
vector
<
T
>
res
;
...
...
@@ -276,4 +272,3 @@ main(int argc, char* argv[]){
/*the next step is to construct encrypted insert query*/
return
0
;
}
debug/store.cc
View file @
c4267e97
#include "debug/store.hh"
#include "wrapper/common.hh"
static
void
write_meta
(
rawMySQLReturnValue
&
resraw
,
std
::
vector
<
transField
>
&
res
,
string
db
,
string
table
){
#include "wrapper/reuse.hh"
static
std
::
string
embeddedDir
=
"/t/cryt/shadow"
;
//global map, for each client, we have one WrapperState which contains ProxyState.
static
std
::
map
<
std
::
string
,
WrapperState
*>
clients
;
//This connection mimics the behaviour of MySQL-Proxy
Connect
*
globalConn
;
//must be static, or we get "no previous declaration"
//execute the query and get the rawReturnVale, this struct can be copied.
static
void
init
(){
std
::
string
client
=
"192.168.1.1:1234"
;
//one Wrapper per user.
clients
[
client
]
=
new
WrapperState
();
//Connect phase
ConnectionInfo
ci
(
"localhost"
,
"root"
,
"letmein"
,
3306
);
const
std
::
string
master_key
=
"113341234"
;
char
*
buffer
;
if
((
buffer
=
getcwd
(
NULL
,
0
))
==
NULL
){
perror
(
"getcwd error"
);
}
embeddedDir
=
std
::
string
(
buffer
)
+
"/shadow"
;
SharedProxyState
*
shared_ps
=
new
SharedProxyState
(
ci
,
embeddedDir
,
master_key
,
determineSecurityRating
());
assert
(
0
==
mysql_thread_init
());
//we init embedded database here.
clients
[
client
]
->
ps
=
std
::
unique_ptr
<
ProxyState
>
(
new
ProxyState
(
*
shared_ps
));
clients
[
client
]
->
ps
->
safeCreateEmbeddedTHD
();
//Connect end!!
globalConn
=
new
Connect
(
ci
.
server
,
ci
.
user
,
ci
.
passwd
,
ci
.
port
);
}
//query for testing purposes
static
std
::
string
getTestQuery
(
SchemaInfo
&
schema
,
std
::
vector
<
FieldMeta_Wrapper
>
&
tfds
,
std
::
string
db
=
"tdb"
,
std
::
string
table
=
"student1"
){
std
::
string
res
=
"SELECT "
;
const
std
::
unique_ptr
<
IdentityMetaKey
>
dbmeta_key
(
new
IdentityMetaKey
(
db
));
//get databaseMeta, search in the map
DatabaseMeta
*
dbm
=
schema
.
getChild
(
*
dbmeta_key
);
const
TableMeta
&
tbm
=
*
((
*
dbm
).
getChild
(
IdentityMetaKey
(
table
)));
std
::
string
annotablename
=
tbm
.
getAnonTableName
();
//then a list of onion names
for
(
auto
item
:
tfds
){
for
(
auto
index
:
item
.
choosenOnions
){
res
+=
item
.
fields
[
index
];
res
+=
" , "
;
}
if
(
item
.
hasSalt
){
res
+=
item
.
originalFm
->
getSaltName
()
+
" , "
;
}
}
res
=
res
.
substr
(
0
,
res
.
size
()
-
2
);
res
=
res
+
"FROM `"
+
db
+
std
::
string
(
"`.`"
)
+
annotablename
+
"`"
;
return
res
;
}
static
void
write_meta
(
rawMySQLReturnValue
&
resraw
,
std
::
vector
<
FieldMeta_Wrapper
>
&
res
,
string
db
,
string
table
){
metadata_files
mf
;
mf
.
set_db_table
(
db
,
table
);
vector
<
vector
<
int
>>
selected_field_types
;
...
...
@@ -52,6 +112,8 @@ static void write_meta(rawMySQLReturnValue& resraw,std::vector<transField> &res,
mf
.
set_has_salt
(
has_salt
);
mf
.
serialize
();
}
static
void
write_row_data
(
rawMySQLReturnValue
&
resraw
,
string
db
,
string
table
){
vector
<
FILE
*>
data_files
;
string
prefix
=
string
(
"data/"
)
+
db
+
"/"
+
table
+
"/"
;
...
...
@@ -74,18 +136,19 @@ static void write_row_data(rawMySQLReturnValue& resraw,string db, string table){
}
}
static
void
write_raw_data_to_files
(
rawMySQLReturnValue
&
resraw
,
std
::
vector
<
transField
>
&
res
,
string
db
,
string
table
){
void
write_raw_data_to_files
(
rawMySQLReturnValue
&
resraw
,
std
::
vector
<
FieldMeta_Wrapper
>
&
res
,
string
db
,
string
table
){
//write metafiles
write_meta
(
resraw
,
res
,
db
,
table
);
//write datafiles
write_row_data
(
resraw
,
db
,
table
);
}
static
void
store
(
std
::
string
db
,
std
::
string
table
){
std
::
unique_ptr
<
SchemaInfo
>
schema
=
myLoadSchemaInfo
();
std
::
unique_ptr
<
SchemaInfo
>
schema
=
myLoadSchemaInfo
(
embeddedDir
);
//get all the fields in the tables
std
::
vector
<
FieldMeta
*>
fms
=
getFieldMeta
(
*
schema
,
db
,
table
);
//transform the field so that selected onions can be used
std
::
vector
<
transField
>
res
=
getTransField
(
fms
);
std
::
vector
<
FieldMeta_Wrapper
>
res
=
FieldMeta_to_Wrapper
(
fms
);
for
(
auto
&
item
:
res
){
(
void
)
item
;
...
...
@@ -97,6 +160,7 @@ static void store(std::string db, std::string table){
//write the tuples into files
write_raw_data_to_files
(
resraw
,
res
,
db
,
table
);
}
int
main
(
int
argc
,
char
*
argv
[]){
init
();
...
...
debug/store.hh
deleted
100644 → 0
View file @
417c895b
#pragma once
/*1. store data as column files, and restore data as plaintext insert query
* 2. plaintext insert query should be able to recover directly
* 3. should be able to used exsisting data to reduce the computation overhead(to be implemented)
*/
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <main/rewrite_main.hh>
#include <main/rewrite_util.hh>
using
std
::
cout
;
using
std
::
cin
;
using
std
::
endl
;
using
std
::
vector
;
using
std
::
string
;
using
std
::
to_string
;
class
WrapperState
{
WrapperState
(
const
WrapperState
&
other
);
WrapperState
&
operator
=
(
const
WrapperState
&
rhs
);
KillZone
kill_zone
;
public
:
std
::
string
last_query
;
std
::
string
default_db
;
WrapperState
()
{}
~
WrapperState
()
{}
const
std
::
unique_ptr
<
QueryRewrite
>
&
getQueryRewrite
()
const
{
assert
(
this
->
qr
);
return
this
->
qr
;
}
void
setQueryRewrite
(
std
::
unique_ptr
<
QueryRewrite
>
&&
in_qr
)
{
this
->
qr
=
std
::
move
(
in_qr
);
}
void
selfKill
(
KillZone
::
Where
where
)
{
kill_zone
.
die
(
where
);
}
void
setKillZone
(
const
KillZone
&
kz
)
{
kill_zone
=
kz
;
}
std
::
unique_ptr
<
ProxyState
>
ps
;
std
::
vector
<
SchemaInfoRef
>
schema_info_refs
;
private
:
std
::
unique_ptr
<
QueryRewrite
>
qr
;
};
//representation of one field.
struct
transField
{
bool
hasSalt
;
FieldMeta
*
originalFm
;
vector
<
int
>
choosenOnions
;
//used to construct return meta
int
onionIndex
=
0
;
//onions
std
::
vector
<
std
::
string
>
fields
;
std
::
vector
<
onion
>
onions
;
};
static
std
::
string
embeddedDir
=
"/t/cryt/shadow"
;
//global map, for each client, we have one WrapperState which contains ProxyState.
static
std
::
map
<
std
::
string
,
WrapperState
*>
clients
;
//This connection mimics the behaviour of MySQL-Proxy
Connect
*
globalConn
;
//Return values got by using directly the MySQL c Client
struct
rawMySQLReturnValue
{
std
::
vector
<
std
::
vector
<
std
::
string
>>
rowValues
;
/*data tuples*/
std
::
vector
<
std
::
string
>
fieldNames
;
std
::
vector
<
enum_field_types
>
fieldTypes
;
std
::
vector
<
int
>
lengths
;
std
::
vector
<
int
>
maxlengths
;
/* what's the difference
between length and maxlength?*/
std
::
vector
<
int
>
choosen_onions
;
void
show
();
};
void
rawMySQLReturnValue
::
show
(){
cout
<<
"rowvalues:"
<<
endl
;
for
(
auto
item_vec
:
rowValues
){
for
(
auto
item
:
item_vec
){
cout
<<
item
.
size
()
<<
"
\t
"
;
}
cout
<<
endl
;
}
cout
<<
"types:"
<<
endl
;
for
(
auto
item
:
fieldTypes
){
cout
<<
IS_NUM
(
item
)
<<
"
\t
"
;
}
cout
<<
endl
;
cout
<<
"fieldNames:"
<<
endl
;
for
(
auto
item
:
fieldNames
){
cout
<<
item
<<
"
\t
"
;
}
cout
<<
endl
;
cout
<<
"lengths:"
<<
endl
;
for
(
auto
item
:
lengths
){
cout
<<
item
<<
"
\t
"
;
}
cout
<<
endl
;
cout
<<
"maxlengths:"
<<
endl
;
for
(
auto
item
:
maxlengths
){
cout
<<
item
<<
"
\t
"
;
}
cout
<<
endl
;
}
static
void
init
(){
std
::
string
client
=
"192.168.1.1:1234"
;
//one Wrapper per user.
clients
[
client
]
=
new
WrapperState
();
//Connect phase
ConnectionInfo
ci
(
"localhost"
,
"root"
,
"letmein"
,
3306
);
const
std
::
string
master_key
=
"113341234"
;
char
*
buffer
;
if
((
buffer
=
getcwd
(
NULL
,
0
))
==
NULL
){
perror
(
"getcwd error"
);
}
embeddedDir
=
std
::
string
(
buffer
)
+
"/shadow"
;
SharedProxyState
*
shared_ps
=
new
SharedProxyState
(
ci
,
embeddedDir
,
master_key
,
determineSecurityRating
());
assert
(
0
==
mysql_thread_init
());
//we init embedded database here.
clients
[
client
]
->
ps
=
std
::
unique_ptr
<
ProxyState
>
(
new
ProxyState
(
*
shared_ps
));
clients
[
client
]
->
ps
->
safeCreateEmbeddedTHD
();
//Connect end!!
globalConn
=
new
Connect
(
ci
.
server
,
ci
.
user
,
ci
.
passwd
,
ci
.
port
);
}
//must be static, or we get "no previous declaration"
//execute the query and get the rawReturnVale, this struct can be copied.
static
rawMySQLReturnValue
executeAndGetResultRemote
(
Connect
*
curConn
,
std
::
string
query
){
std
::
unique_ptr
<
DBResult
>
dbres
;
curConn
->
execute
(
query
,
&
dbres
);
rawMySQLReturnValue
myRaw
;
if
(
dbres
==
nullptr
||
dbres
->
n
==
NULL
){
std
::
cout
<<
"no results"
<<
std
::
endl
;
return
myRaw
;
}
int
num
=
mysql_num_rows
(
dbres
->
n
);
int
numOfFields
=
mysql_num_fields
(
dbres
->
n
);
MYSQL_FIELD
*
field
;
MYSQL_ROW
row
;
if
(
num
!=
0
){
while
(
(
row
=
mysql_fetch_row
(
dbres
->
n
))
){
//what's the difference between fieldlen
unsigned
long
*
fieldLen
=
mysql_fetch_lengths
(
dbres
->
n
);
std
::
vector
<
std
::
string
>
curRow
;
for
(
int
i
=
0
;
i
<
numOfFields
;
i
++
){
if
(
i
==
0
)
{
while
(
(
field
=
mysql_fetch_field
(
dbres
->
n
))
)
{
myRaw
.
fieldNames
.
push_back
(
std
::
string
(
field
->
name
));
myRaw
.
fieldTypes
.
push_back
(
field
->
type
);
//myRaw.lengths.push_back(field->length);
//myRaw.lengths.push_back(fieldLen[i]);
myRaw
.
lengths
.
push_back
(
field
->
max_length
);
myRaw
.
maxlengths
.
push_back
(
field
->
max_length
);
//cout<<field->length<<"::"<<field->max_length<<endl;
}
}
if
(
row
[
i
]
==
NULL
)
curRow
.
push_back
(
"NULL"
);
else
curRow
.
push_back
(
std
::
string
(
row
[
i
],
fieldLen
[
i
]));
}
myRaw
.
rowValues
.
push_back
(
curRow
);
}
}
return
myRaw
;
}
//first step of back
static
std
::
vector
<
FieldMeta
*>
getFieldMeta
(
SchemaInfo
&
schema
,
std
::
string
db
=
"tdb"
,
std
::
string
table
=
"student"
)
{
const
std
::
unique_ptr
<
AES_KEY
>
&
TK
=
std
::
unique_ptr
<
AES_KEY
>
(
getKey
(
std
::
string
(
"113341234"
)));
Analysis
analysis
(
db
,
schema
,
TK
,
SECURITY_RATING
::
SENSITIVE
);
if
(
analysis
.
databaseMetaExists
(
db
)){
const
DatabaseMeta
&
dbm
=
analysis
.
getDatabaseMeta
(
db
);
TableMeta
&
tbm
=
*
dbm
.
getChild
(
IdentityMetaKey
(
table
));
return
tbm
.
orderedFieldMetas
();
}
else
{
std
::
cout
<<
"data base not exists"
<<
std
::
endl
;
return
std
::
vector
<
FieldMeta
*>
();
}
}
static
std
::
unique_ptr
<
SchemaInfo
>
myLoadSchemaInfo
()
{
std
::
unique_ptr
<
Connect
>
e_conn
(
Connect
::
getEmbedded
(
embeddedDir
));
std
::
unique_ptr
<
SchemaInfo
>
schema
(
new
SchemaInfo
());
std
::
function
<
DBMeta
*
(
DBMeta
*
const
)
>
loadChildren
=
[
&
loadChildren
,
&
e_conn
](
DBMeta
*
const
parent
)
{
auto
kids
=
parent
->
fetchChildren
(
e_conn
);
for
(
auto
it
:
kids
)
{
loadChildren
(
it
);
}
return
parent
;
};
//load all metadata and then store it in schema
loadChildren
(
schema
.
get
());
Analysis
analysis
(
std
::
string
(
"student"
),
*
schema
,
std
::
unique_ptr
<
AES_KEY
>
(
getKey
(
std
::
string
(
"113341234"
))),
SECURITY_RATING
::
SENSITIVE
);
return
schema
;
}
/*for each field, convert the format to transField*/
static
std
::
vector
<
transField
>
getTransField
(
std
::
vector
<
FieldMeta
*>
pfms
){
std
::
vector
<
transField
>
res
;
//for every field
for
(
auto
pfm
:
pfms
){
transField
tf
;
tf
.
originalFm
=
pfm
;
for
(
std
::
pair
<
const
OnionMetaKey
*
,
OnionMeta
*>
&
ompair
:
pfm
->
orderedOnionMetas
()){
tf
.
fields
.
push_back
((
ompair
.
second
)
->
getAnonOnionName
());
tf
.
onions
.
push_back
(
ompair
.
first
->
getValue
());
}
if
(
pfm
->
getHasSalt
()){
tf
.
hasSalt
=
true
;
tf
.
fields
.
push_back
(
pfm
->
getSaltName
());
}
res
.
push_back
(
tf
);
}
return
res
;
}
//query for testing purposes
static
std
::
string
getTestQuery
(
SchemaInfo
&
schema
,
std
::
vector
<
transField
>
&
tfds
,
std
::
string
db
=
"tdb"
,
std
::
string
table
=
"student1"
){
std
::
string
res
=
"SELECT "
;
const
std
::
unique_ptr
<
IdentityMetaKey
>
dbmeta_key
(
new
IdentityMetaKey
(
db
));
//get databaseMeta, search in the map
DatabaseMeta
*
dbm
=
schema
.
getChild
(
*
dbmeta_key
);
const
TableMeta
&
tbm
=
*
((
*
dbm
).
getChild
(
IdentityMetaKey
(
table
)));
std
::
string
annotablename
=
tbm
.
getAnonTableName
();
//then a list of onion names
for
(
auto
item
:
tfds
){
for
(
auto
index
:
item
.
choosenOnions
){
res
+=
item
.
fields
[
index
];
res
+=
" , "
;
}
if
(
item
.
hasSalt
){
res
+=
item
.
originalFm
->
getSaltName
()
+
" , "
;
}
}
res
=
res
.
substr
(
0
,
res
.
size
()
-
2
);
res
=
res
+
"FROM `"
+
db
+
std
::
string
(
"`.`"
)
+
annotablename
+
"`"
;
return
res
;
}
debug/try_select_back.cc
0 → 100644
View file @
c4267e97
/*
To make this work properly, you should at least make sure that the database tdb exists.
*/
#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <main/Connect.hh>
#include <main/rewrite_util.hh>
#include <main/sql_handler.hh>
#include <main/dml_handler.hh>
#include <main/ddl_handler.hh>
#include <main/CryptoHandlers.hh>
static
std
::
string
embeddedDir
=
"/t/cryt/shadow"
;
SharedProxyState
*
shared_ps
;
Connect
*
globalConn
;
ProxyState
*
ps
;
struct
rawReturnValue
{
std
::
vector
<
std
::
vector
<
std
::
string
>
>
rowValues
;
std
::
vector
<
std
::
string
>
fieldNames
;
std
::
vector
<
int
>
fieldTypes
;
};
//helper function for transforming the rawReturnValue
static
Item_null
*
make_null
(
const
std
::
string
&
name
=
""
){
char
*
const
n
=
current_thd
->
strdup
(
name
.
c_str
());
return
new
Item_null
(
n
);
}
//helper function for transforming the rawReturnValue
static
std
::
vector
<
Item
*>
itemNullVector
(
unsigned
int
count
)
{
std
::
vector
<
Item
*>
out
;
for
(
unsigned
int
i
=
0
;
i
<
count
;
++
i
)
{
out
.
push_back
(
make_null
());
}
return
out
;
}
static
ResType
MygetResTypeFromLuaTable
(
bool
isNULL
,
rawReturnValue
*
inRow
=
NULL
,
int
in_last_insert_id
=
0
){
std
::
vector
<
std
::
string
>
names
;
std
::
vector
<
enum_field_types
>
types
;
std
::
vector
<
std
::
vector
<
Item
*>
>
rows
;
//return NULL restype
if
(
isNULL
){
return
ResType
(
true
,
0
,
0
,
std
::
move
(
names
),
std
::
move
(
types
),
std
::
move
(
rows
));
}
else
{
for
(
auto
inNames
:
inRow
->
fieldNames
){
names
.
push_back
(
inNames
);
}
for
(
auto
inTypes
:
inRow
->
fieldTypes
){
types
.
push_back
(
static_cast
<
enum_field_types
>
(
inTypes
));
}
for
(
auto
inRows
:
inRow
->
rowValues
)
{
std
::
vector
<
Item
*>
curTempRow
=
itemNullVector
(
types
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)(
inRows
.
size
());
i
++
){
curTempRow
[
i
]
=
(
MySQLFieldTypeToItem
(
types
[
i
],
inRows
[
i
])
);
}
rows
.
push_back
(
curTempRow
);
}
return
ResType
(
true
,
0
,
in_last_insert_id
,
std
::
move
(
names
),
std
::
move
(
types
),
std
::
move
(
rows
));
}
}
static
rawReturnValue
executeAndGetResultRemote
(
Connect
*
curConn
,
std
::
string
query
){
std
::
unique_ptr
<
DBResult
>
dbres
;
curConn
->
execute
(
query
,
&
dbres
);
rawReturnValue
myRaw
;
if
(
dbres
==
nullptr
||
dbres
->
n
==
NULL
){
//std::cout<<"no results"<<std::endl;
return
myRaw
;
}
int
num
=
mysql_num_rows
(
dbres
->
n
);
if
(
num
!=
0
)
std
::
cout
<<
"num of rows: "
<<
num
<<
std
::
endl
;
int
numOfFields
=
mysql_num_fields
(
dbres
->
n
);
if
(
numOfFields
!=
0
)
std
::
cout
<<
"num of fields: "
<<
numOfFields
<<
std
::
endl
;
MYSQL_FIELD
*
field
;
MYSQL_ROW
row
;
if
(
num
!=
0
){
while
(
(
row
=
mysql_fetch_row
(
dbres
->
n
))
){
unsigned
long
*
fieldLen
=
mysql_fetch_lengths
(
dbres
->
n
);
std
::
vector
<
std
::
string
>
curRow
;
for
(
int
i
=
0
;
i
<
numOfFields
;
i
++
){
if
(
i
==
0
)
{
while
(
(
field
=
mysql_fetch_field
(
dbres
->
n
))
)
{
myRaw
.
fieldNames
.
push_back
(
std
::
string
(
field
->
name
));
myRaw
.
fieldTypes
.
push_back
(
field
->
type
);
}
}
if
(
row
[
i
]
==
NULL
)
curRow
.
push_back
(
"NULL"
);
else
curRow
.
push_back
(
std
::
string
(
row
[
i
],
fieldLen
[
i
]));
}
myRaw
.
rowValues
.
push_back
(
curRow
);
}
}
return
myRaw
;
}
static
void
parseResType
(
const
ResType
&
rd
)
{
for
(
auto
name
:
rd
.
names
){
std
::
cout
<<
name
<<
"
\t
"
;
}
std
::
cout
<<
std
::
endl
;
for
(
auto
row
:
rd
.
rows
){
for
(
auto
item
:
row
){
std
::
cout
<<
ItemToString
(
*
item
)
<<
"
\t
"
;
}
std
::
cout
<<
std
::
endl
;
}
}
static
void
sp_next
(
std
::
string
db
,
std
::
string
query
,
QueryRewrite
*
qr
,
ResType
inRes
){
ps
->
safeCreateEmbeddedTHD
();
//then we come to the next step.
const
ResType
&
res
=
inRes
;
//MygetResTypeFromLuaTable(true);
try
{
NextParams
nparams
(
*
ps
,
db
,
query
);
const
auto
&
new_results
=
qr
->
executor
->
next
(
res
,
nparams
);
const
auto
&
result_type
=
new_results
.
first
;
switch
(
result_type
){
//execute the query, fetch the results, and call next again
case
AbstractQueryExecutor
:
:
ResultType
::
QUERY_COME_AGAIN
:
{
// std::cout<<RED_BEGIN<<"case one"<<COLOR_END<<std::endl;
const
auto
&
output
=
std
::
get
<
1
>
(
new_results
)
->
extract
<
std
::
pair
<
bool
,
std
::
string
>
>
();
const
auto
&
next_query
=
output
.
second
;
//here we execute the query against the remote database, and get rawReturnValue
rawReturnValue
resRemote
=
executeAndGetResultRemote
(
globalConn
,
next_query
);
//transform rawReturnValue first
const
auto
&
againGet
=
MygetResTypeFromLuaTable
(
false
,
&
resRemote
);
sp_next
(
db
,
query
,
qr
,
againGet
);
break
;
}
//only execute the query, without processing the retults
case
AbstractQueryExecutor
:
:
ResultType
::
QUERY_USE_RESULTS
:
{
// std::cout<<RED_BEGIN<<"case two"<<COLOR_END<<std::endl;
const
auto
&
new_query
=
std
::
get
<
1
>
(
new_results
)
->
extract
<
std
::
string
>
();
auto
resRemote
=
executeAndGetResultRemote
(
globalConn
,
new_query
);
break
;
}
//return the results to the client directly
case
AbstractQueryExecutor
:
:
ResultType
::
RESULTS
:
{
// std::cout<<RED_BEGIN<<"case three"<<COLOR_END<<std::endl;
const
auto
&
res
=
new_results
.
second
->
extract
<
ResType
>
();
parseResType
(
res
);
break
;
}
default
:
{
std
::
cout
<<
"case default"
<<
std
::
endl
;
}
}
}
catch
(...){
std
::
cout
<<
"next error"
<<
std
::
endl
;
}
}
//===================================================gather part==========================================================
static
RewritePlan
*
my_gather
(
const
Item_field
&
i
,
Analysis
&
a
){
const
std
::
string
fieldname
=
i
.
field_name
;
const
std
::
string
table
=
i
.
table_name
;
//we donot deduce here
FieldMeta
&
fm
=
a
.
getFieldMeta
(
a
.
getDatabaseName
(),
table
,
fieldname
);
const
EncSet
es
=
EncSet
(
a
,
&
fm
);
const
std
::
string
why
=
"is a field"
;
reason
rsn
(
es
,
why
,
i
);
return
new
RewritePlan
(
es
,
rsn
);
}
static
void
my_gatherAndAddAnalysisRewritePlan
(
const
Item
&
i
,
Analysis
&
a
){
a
.
rewritePlans
[
&
i
]
=
std
::
unique_ptr
<
RewritePlan
>
(
my_gather
(
static_cast
<
const
Item_field
&>
(
i
),
a
));
}
static
void
my_process_select_lex
(
const
st_select_lex
&
select_lex
,
Analysis
&
a
){
auto
item_it
=
RiboldMYSQL
::
constList_iterator
<
Item
>
(
select_lex
.
item_list
);
for
(;;)
{
/*not used in normal insert queries;
processes id and name in the table student
*/
const
Item
*
const
item
=
item_it
++
;
if
(
!
item
)
break
;
my_gatherAndAddAnalysisRewritePlan
(
*
item
,
a
);
}
}
static
void
my_gather_select
(
Analysis
&
a
,
LEX
*
const
lex
){
my_process_select_lex
(
lex
->
select_lex
,
a
);
}
//==========================================================Rewrite=================================================
static
void
my_addToReturn
(
ReturnMeta
*
const
rm
,
int
pos
,
const
OLK
&
constr
,
bool
has_salt
,
const
std
::
string
&
name
){
const
bool
test
=
static_cast
<
unsigned
int
>
(
pos
)
==
rm
->
rfmeta
.
size
();
TEST_TextMessageError
(
test
,
"ReturnMeta has badly ordered"
" ReturnFields!"
);
const
int
salt_pos
=
has_salt
?
pos
+
1
:
-
1
;
std
::
pair
<
int
,
ReturnField
>
pair
(
pos
,
ReturnField
(
false
,
name
,
constr
,
salt_pos
));
rm
->
rfmeta
.
insert
(
pair
);
}
static
void
my_addSaltToReturn
(
ReturnMeta
*
const
rm
,
int
pos
){
const
bool
test
=
static_cast
<
unsigned
int
>
(
pos
)
==
rm
->
rfmeta
.
size
();
TEST_TextMessageError
(
test
,
"ReturnMeta has badly ordered"
" ReturnFields!"
);
std
::
pair
<
int
,
ReturnField
>
pair
(
pos
,
ReturnField
(
true
,
""
,
OLK
::
invalidOLK
(),
-
1
));
rm
->
rfmeta
.
insert
(
pair
);
}
static
Item
*
my_do_rewrite_type
(
const
Item_field
&
i
,
const
OLK
&
constr
,
const
RewritePlan
&
rp
,
Analysis
&
a
)
{
const
std
::
string
&
db_name
=
a
.
getDatabaseName
();
const
std
::
string
plain_table_name
=
i
.
table_name
;
const
FieldMeta
&
fm
=
a
.
getFieldMeta
(
db_name
,
plain_table_name
,
i
.
field_name
);
//check if we need onion adjustment
const
OnionMeta
&
om
=
a
.
getOnionMeta
(
db_name
,
plain_table_name
,
i
.
field_name
,
constr
.
o
);
const
SECLEVEL
onion_level
=
a
.
getOnionLevel
(
om
);
assert
(
onion_level
!=
SECLEVEL
::
INVALID
);
if
(
constr
.
l
<
onion_level
)
{
//need adjustment, throw exception
const
TableMeta
&
tm
=
a
.
getTableMeta
(
db_name
,
plain_table_name
);
throw
OnionAdjustExcept
(
tm
,
fm
,
constr
.
o
,
constr
.
l
);
}
bool
is_alias
;
const
std
::
string
anon_table_name
=
a
.
getAnonTableName
(
db_name
,
plain_table_name
,
&
is_alias
);
const
std
::
string
anon_field_name
=
om
.
getAnonOnionName
();
Item_field
*
const
res
=
make_item_field
(
i
,
anon_table_name
,
anon_field_name
);
// HACK: to get aliases to work in DELETE FROM statements
if
(
a
.
inject_alias
&&
is_alias
)
{
res
->
db_name
=
NULL
;
}
// This information is only relevant if it comes from a
// HAVING clause.
// FIXME: Enforce this semantically.
a
.
item_cache
[
&
i
]
=
std
::
make_pair
(
res
,
constr
);
return
res
;
}
static
Item
*
my_rewrite
(
const
Item
&
i
,
const
EncSet
&
req_enc
,
Analysis
&
a
){
const
std
::
unique_ptr
<
RewritePlan
>
&
rp
=
constGetAssert
(
a
.
rewritePlans
,
&
i
);
const
EncSet
solution
=
rp
->
es_out
.
intersect
(
req_enc
);
TEST_NoAvailableEncSet
(
solution
,
i
.
type
(),
req_enc
,
rp
->
r
.
why
,
std
::
vector
<
std
::
shared_ptr
<
RewritePlan
>
>
());
return
my_do_rewrite_type
(
static_cast
<
const
Item_field
&>
(
i
),
solution
.
chooseOne
(),
*
rp
.
get
(),
a
);
}
static
void
my_rewrite_proj
(
const
Item
&
i
,
const
RewritePlan
&
rp
,
Analysis
&
a
,
List
<
Item
>
*
const
newList
)
{
AssignOnce
<
OLK
>
olk
;
AssignOnce
<
Item
*>
ir
;
if
(
i
.
type
()
==
Item
::
Type
::
FIELD_ITEM
)
{
const
Item_field
&
field_i
=
static_cast
<
const
Item_field
&>
(
i
);
const
auto
&
cached_rewritten_i
=
a
.
item_cache
.
find
(
&
field_i
);
if
(
cached_rewritten_i
!=
a
.
item_cache
.
end
())
{
ir
=
cached_rewritten_i
->
second
.
first
;
olk
=
cached_rewritten_i
->
second
.
second
;
}
else
{
ir
=
my_rewrite
(
i
,
rp
.
es_out
,
a
);
olk
=
rp
.
es_out
.
chooseOne
();
}
}
else
{
exit
(
0
);
}
//和insert不同, select的时候, 只要一个洋葱, 选取一个进行改写就可以了, 不需要扩展.
assert
(
ir
.
assigned
()
&&
ir
.
get
());
newList
->
push_back
(
ir
.
get
());
const
bool
use_salt
=
needsSalt
(
olk
.
get
());
// This line implicity handles field aliasing for at least some cases.
// As i->name can/will be the alias.
my_addToReturn
(
&
a
.
rmeta
,
a
.
pos
++
,
olk
.
get
(),
use_salt
,
i
.
name
);
if
(
use_salt
)
{
TEST_TextMessageError
(
Item
::
Type
::
FIELD_ITEM
==
ir
.
get
()
->
type
(),
"a projection requires a salt and is not a field; cryptdb"
" does not currently support such behavior"
);
const
std
::
string
&
anon_table_name
=
static_cast
<
Item_field
*>
(
ir
.
get
())
->
table_name
;
const
std
::
string
&
anon_field_name
=
olk
.
get
().
key
->
getSaltName
();
Item_field
*
const
ir_field
=
make_item_field
(
*
static_cast
<
Item_field
*>
(
ir
.
get
()),
anon_table_name
,
anon_field_name
);
newList
->
push_back
(
ir_field
);
my_addSaltToReturn
(
&
a
.
rmeta
,
a
.
pos
++
);
}
}
static
st_select_lex
*
my_rewrite_select_lex
(
const
st_select_lex
&
select_lex
,
Analysis
&
a
){
//do not support filter
st_select_lex
*
const
new_select_lex
=
copyWithTHD
(
&
select_lex
);
auto
item_it
=
RiboldMYSQL
::
constList_iterator
<
Item
>
(
select_lex
.
item_list
);
List
<
Item
>
newList
;
//rewrite item
for
(;;)
{
const
Item
*
const
item
=
item_it
++
;
if
(
!
item
)
break
;
my_rewrite_proj
(
*
item
,
*
constGetAssert
(
a
.
rewritePlans
,
item
).
get
(),
//get the rewrite plain
a
,
&
newList
);
}
new_select_lex
->
item_list
=
newList
;
return
new_select_lex
;
}
static
AbstractQueryExecutor
*
my_rewrite_select
(
Analysis
&
a
,
LEX
*
lex
){
LEX
*
const
new_lex
=
copyWithTHD
(
lex
);
//this is actually table list instead of join list.
new_lex
->
select_lex
.
top_join_list
=
rewrite_table_list
(
lex
->
select_lex
.
top_join_list
,
a
);
SELECT_LEX
*
const
select_lex_res
=
my_rewrite_select_lex
(
new_lex
->
select_lex
,
a
);
set_select_lex
(
new_lex
,
select_lex_res
);
return
new
DMLQueryExecutor
(
*
new_lex
,
a
.
rmeta
);
}
static
void
testCreateTableHandler
(
std
::
string
query
,
std
::
string
db
=
"tdb"
){
std
::
unique_ptr
<
Connect
>
e_conn
(
Connect
::
getEmbedded
(
embeddedDir
));
std
::
unique_ptr
<
SchemaInfo
>
schema
(
new
SchemaInfo
());
std
::
function
<
DBMeta
*
(
DBMeta
*
const
)
>
loadChildren
=
[
&
loadChildren
,
&
e_conn
](
DBMeta
*
const
parent
)
{
auto
kids
=
parent
->
fetchChildren
(
e_conn
);
for
(
auto
it
:
kids
)
{
loadChildren
(
it
);
}
return
parent
;
};
//load all metadata and then store it in schema
loadChildren
(
schema
.
get
());
const
std
::
unique_ptr
<
AES_KEY
>
&
TK
=
std
::
unique_ptr
<
AES_KEY
>
(
getKey
(
std
::
string
(
"113341234"
)));
//just like what we do in Rewrite::rewrite,dispatchOnLex
Analysis
analysis
(
std
::
string
(
"tdb"
),
*
schema
,
TK
,
SECURITY_RATING
::
SENSITIVE
);
assert
(
analysis
.
getMasterKey
().
get
()
!=
NULL
);
assert
(
getKey
(
std
::
string
(
"113341234"
))
!=
NULL
);
std
::
unique_ptr
<
query_parse
>
p
;
p
=
std
::
unique_ptr
<
query_parse
>
(
new
query_parse
(
db
,
query
));
LEX
*
const
lex
=
p
->
lex
();
std
::
string
table
(
lex
->
select_lex
.
table_list
.
first
->
table_name
);
my_gather_select
(
analysis
,
lex
);
auto
executor
=
my_rewrite_select
(
analysis
,
lex
);
QueryRewrite
*
qr
=
new
QueryRewrite
(
QueryRewrite
(
true
,
analysis
.
rmeta
,
analysis
.
kill_zone
,
executor
));
sp_next
(
db
,
query
,
qr
,
MygetResTypeFromLuaTable
(
true
));
}
int
main
()
{
char
*
buffer
;
if
((
buffer
=
getcwd
(
NULL
,
0
))
==
NULL
){
perror
(
"getcwd error"
);
}
embeddedDir
=
std
::
string
(
buffer
)
+
"/shadow"
;
const
std
::
string
master_key
=
"113341234"
;
ConnectionInfo
ci
(
"localhost"
,
"root"
,
"letmein"
,
3306
);
shared_ps
=
new
SharedProxyState
(
ci
,
embeddedDir
,
master_key
,
determineSecurityRating
());
assert
(
shared_ps
!=
NULL
);
ps
=
new
ProxyState
(
*
shared_ps
);
globalConn
=
new
Connect
(
ci
.
server
,
ci
.
user
,
ci
.
passwd
,
ci
.
port
);
globalConn
->
execute
(
"use tdb"
);
ps
->
safeCreateEmbeddedTHD
();
std
::
string
query1
=
"select * from student;"
;
std
::
vector
<
std
::
string
>
querys
{
query1
};
for
(
auto
item
:
querys
){
std
::
cout
<<
item
<<
std
::
endl
;
testCreateTableHandler
(
item
);
std
::
cout
<<
std
::
endl
;
}
return
0
;
}
debug/try_select_data.cc
View file @
c4267e97
...
...
@@ -13,109 +13,13 @@ To make this work properly, you should at least make sure that the database tdb
#include <main/dml_handler.hh>
#include <main/ddl_handler.hh>
#include <main/CryptoHandlers.hh>
#include "wrapper/reuse.hh"
static
std
::
string
embeddedDir
=
"/t/cryt/shadow"
;
SharedProxyState
*
shared_ps
;
Connect
*
globalConn
;
ProxyState
*
ps
;
struct
rawReturnValue
{
std
::
vector
<
std
::
vector
<
std
::
string
>
>
rowValues
;
std
::
vector
<
std
::
string
>
fieldNames
;
std
::
vector
<
int
>
fieldTypes
;
};
//helper function for transforming the rawReturnValue
static
Item_null
*
make_null
(
const
std
::
string
&
name
=
""
){
char
*
const
n
=
current_thd
->
strdup
(
name
.
c_str
());
return
new
Item_null
(
n
);
}
//helper function for transforming the rawReturnValue
static
std
::
vector
<
Item
*>
itemNullVector
(
unsigned
int
count
)
{
std
::
vector
<
Item
*>
out
;
for
(
unsigned
int
i
=
0
;
i
<
count
;
++
i
)
{
out
.
push_back
(
make_null
());
}
return
out
;
}
static
ResType
MygetResTypeFromLuaTable
(
bool
isNULL
,
rawReturnValue
*
inRow
=
NULL
,
int
in_last_insert_id
=
0
){
std
::
vector
<
std
::
string
>
names
;
std
::
vector
<
enum_field_types
>
types
;
std
::
vector
<
std
::
vector
<
Item
*>
>
rows
;
//return NULL restype
if
(
isNULL
){
return
ResType
(
true
,
0
,
0
,
std
::
move
(
names
),
std
::
move
(
types
),
std
::
move
(
rows
));
}
else
{
for
(
auto
inNames
:
inRow
->
fieldNames
){
names
.
push_back
(
inNames
);
}
for
(
auto
inTypes
:
inRow
->
fieldTypes
){
types
.
push_back
(
static_cast
<
enum_field_types
>
(
inTypes
));
}
for
(
auto
inRows
:
inRow
->
rowValues
)
{
std
::
vector
<
Item
*>
curTempRow
=
itemNullVector
(
types
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)(
inRows
.
size
());
i
++
){
curTempRow
[
i
]
=
(
MySQLFieldTypeToItem
(
types
[
i
],
inRows
[
i
])
);
}
rows
.
push_back
(
curTempRow
);
}
return
ResType
(
true
,
0
,
in_last_insert_id
,
std
::
move
(
names
),
std
::
move
(
types
),
std
::
move
(
rows
));
}
}
static
rawReturnValue
executeAndGetResultRemote
(
Connect
*
curConn
,
std
::
string
query
){
std
::
unique_ptr
<
DBResult
>
dbres
;
curConn
->
execute
(
query
,
&
dbres
);
rawReturnValue
myRaw
;
if
(
dbres
==
nullptr
||
dbres
->
n
==
NULL
){
//std::cout<<"no results"<<std::endl;
return
myRaw
;
}
int
num
=
mysql_num_rows
(
dbres
->
n
);
if
(
num
!=
0
)
std
::
cout
<<
"num of rows: "
<<
num
<<
std
::
endl
;
int
numOfFields
=
mysql_num_fields
(
dbres
->
n
);
if
(
numOfFields
!=
0
)
std
::
cout
<<
"num of fields: "
<<
numOfFields
<<
std
::
endl
;
MYSQL_FIELD
*
field
;
MYSQL_ROW
row
;
if
(
num
!=
0
){
while
(
(
row
=
mysql_fetch_row
(
dbres
->
n
))
){
unsigned
long
*
fieldLen
=
mysql_fetch_lengths
(
dbres
->
n
);
std
::
vector
<
std
::
string
>
curRow
;
for
(
int
i
=
0
;
i
<
numOfFields
;
i
++
){
if
(
i
==
0
)
{
while
(
(
field
=
mysql_fetch_field
(
dbres
->
n
))
)
{
myRaw
.
fieldNames
.
push_back
(
std
::
string
(
field
->
name
));
myRaw
.
fieldTypes
.
push_back
(
field
->
type
);
}
}
if
(
row
[
i
]
==
NULL
)
curRow
.
push_back
(
"NULL"
);
else
curRow
.
push_back
(
std
::
string
(
row
[
i
],
fieldLen
[
i
]));
}
myRaw
.
rowValues
.
push_back
(
curRow
);
}
}
return
myRaw
;
}
static
void
parseResType
(
const
ResType
&
rd
)
{
for
(
auto
name
:
rd
.
names
){
...
...
@@ -130,60 +34,43 @@ void parseResType(const ResType &rd) {
}
}
static
void
sp_next
(
std
::
string
db
,
std
::
string
query
,
QueryRewrite
*
qr
,
ResType
inRes
){
static
void
sp_next_second
(
std
::
string
db
,
std
::
string
query
,
QueryRewrite
*
qr
,
ResType
inRes
){
ps
->
safeCreateEmbeddedTHD
();
//then we come to the next step.
const
ResType
&
res
=
inRes
;
//MygetResTypeFromLuaTable(true);
const
ResType
&
res
=
inRes
;
try
{
//AbstractQueryExecutor::ResultType::RESULTS
NextParams
nparams
(
*
ps
,
db
,
query
);
const
auto
&
new_results
=
qr
->
executor
->
next
(
res
,
nparams
);
const
auto
&
result_type
=
new_results
.
first
;
switch
(
result_type
){
//execute the query, fetch the results, and call next again
case
AbstractQueryExecutor
:
:
ResultType
::
QUERY_COME_AGAIN
:
{
// std::cout<<RED_BEGIN<<"case one"<<COLOR_END<<std::endl;
const
auto
&
output
=
std
::
get
<
1
>
(
new_results
)
->
extract
<
std
::
pair
<
bool
,
std
::
string
>
>
();
const
auto
&
next_query
=
output
.
second
;
//here we execute the query against the remote database, and get rawReturnValue
rawReturnValue
resRemote
=
executeAndGetResultRemote
(
globalConn
,
next_query
);
//transform rawReturnValue first
const
auto
&
againGet
=
MygetResTypeFromLuaTable
(
false
,
&
resRemote
);
sp_next
(
db
,
query
,
qr
,
againGet
);
break
;
}
//only execute the query, without processing the retults
case
AbstractQueryExecutor
:
:
ResultType
::
QUERY_USE_RESULTS
:
{
// std::cout<<RED_BEGIN<<"case two"<<COLOR_END<<std::endl;
const
auto
&
new_query
=
std
::
get
<
1
>
(
new_results
)
->
extract
<
std
::
string
>
();
auto
resRemote
=
executeAndGetResultRemote
(
globalConn
,
new_query
);
break
;
}
//return the results to the client directly
case
AbstractQueryExecutor
:
:
ResultType
::
RESULTS
:
{
// std::cout<<RED_BEGIN<<"case three"<<COLOR_END<<std::endl;
const
auto
&
res
=
new_results
.
second
->
extract
<
ResType
>
();
parseResType
(
res
);
break
;
}
default
:
{
std
::
cout
<<
"case default"
<<
std
::
endl
;
}
}
//const auto &result_type = new_results.first;
const
auto
&
res
=
new_results
.
second
->
extract
<
ResType
>
();
parseResType
(
res
);
}
catch
(...){
std
::
cout
<<
"next error"
<<
std
::
endl
;
std
::
cout
<<
"
second
next error"
<<
std
::
endl
;
}
}
//===================================================gather part==========================================================
static
void
sp_next_first
(
std
::
string
db
,
std
::
string
query
,
QueryRewrite
*
qr
,
ResType
inRes
){
ps
->
safeCreateEmbeddedTHD
();
const
ResType
&
res
=
inRes
;
try
{
NextParams
nparams
(
*
ps
,
db
,
query
);
const
auto
&
new_results
=
qr
->
executor
->
next
(
res
,
nparams
);
// const auto &result_type = new_results.first;
//AbstractQueryExecutor::ResultType::QUERY_COME_AGAIN
const
auto
&
output
=
std
::
get
<
1
>
(
new_results
)
->
extract
<
std
::
pair
<
bool
,
std
::
string
>
>
();
const
auto
&
next_query
=
output
.
second
;
//here we execute the query against the remote database, and get rawReturnValue
rawMySQLReturnValue
resRemote
=
executeAndGetResultRemote
(
globalConn
,
next_query
);
//transform rawReturnValue first
const
auto
&
againGet
=
MygetResTypeFromLuaTable
(
false
,
&
resRemote
);
sp_next_second
(
db
,
query
,
qr
,
againGet
);
}
catch
(...){
std
::
cout
<<
"first next error"
<<
std
::
endl
;
}
}
//=================================gather part======================================
static
RewritePlan
*
my_gather
(
const
Item_field
&
i
,
Analysis
&
a
){
...
...
@@ -224,32 +111,7 @@ static void my_gather_select(Analysis &a, LEX *const lex){
}
//==========================================================Rewrite=================================================
static
void
my_addToReturn
(
ReturnMeta
*
const
rm
,
int
pos
,
const
OLK
&
constr
,
bool
has_salt
,
const
std
::
string
&
name
){
const
bool
test
=
static_cast
<
unsigned
int
>
(
pos
)
==
rm
->
rfmeta
.
size
();
TEST_TextMessageError
(
test
,
"ReturnMeta has badly ordered"
" ReturnFields!"
);
const
int
salt_pos
=
has_salt
?
pos
+
1
:
-
1
;
std
::
pair
<
int
,
ReturnField
>
pair
(
pos
,
ReturnField
(
false
,
name
,
constr
,
salt_pos
));
rm
->
rfmeta
.
insert
(
pair
);
}
static
void
my_addSaltToReturn
(
ReturnMeta
*
const
rm
,
int
pos
){
const
bool
test
=
static_cast
<
unsigned
int
>
(
pos
)
==
rm
->
rfmeta
.
size
();
TEST_TextMessageError
(
test
,
"ReturnMeta has badly ordered"
" ReturnFields!"
);
std
::
pair
<
int
,
ReturnField
>
pair
(
pos
,
ReturnField
(
true
,
""
,
OLK
::
invalidOLK
(),
-
1
));
rm
->
rfmeta
.
insert
(
pair
);
}
//===========================================Rewrite=============================================
static
Item
*
my_do_rewrite_type
(
const
Item_field
&
i
,
const
OLK
&
constr
,
...
...
@@ -329,7 +191,7 @@ my_rewrite_proj(const Item &i, const RewritePlan &rp, Analysis &a,
// This line implicity handles field aliasing for at least some cases.
// As i->name can/will be the alias.
my_
addToReturn
(
&
a
.
rmeta
,
a
.
pos
++
,
olk
.
get
(),
use_salt
,
i
.
name
);
addToReturn
(
&
a
.
rmeta
,
a
.
pos
++
,
olk
.
get
(),
use_salt
,
i
.
name
);
if
(
use_salt
)
{
TEST_TextMessageError
(
Item
::
Type
::
FIELD_ITEM
==
ir
.
get
()
->
type
(),
...
...
@@ -342,7 +204,7 @@ my_rewrite_proj(const Item &i, const RewritePlan &rp, Analysis &a,
make_item_field
(
*
static_cast
<
Item_field
*>
(
ir
.
get
()),
anon_table_name
,
anon_field_name
);
newList
->
push_back
(
ir_field
);
my_
addSaltToReturn
(
&
a
.
rmeta
,
a
.
pos
++
);
addSaltToReturn
(
&
a
.
rmeta
,
a
.
pos
++
);
}
}
...
...
@@ -375,7 +237,6 @@ AbstractQueryExecutor * my_rewrite_select(Analysis &a, LEX *lex){
//this is actually table list instead of join list.
new_lex
->
select_lex
.
top_join_list
=
rewrite_table_list
(
lex
->
select_lex
.
top_join_list
,
a
);
SELECT_LEX
*
const
select_lex_res
=
my_rewrite_select_lex
(
new_lex
->
select_lex
,
a
);
set_select_lex
(
new_lex
,
select_lex_res
);
return
new
DMLQueryExecutor
(
*
new_lex
,
a
.
rmeta
);
...
...
@@ -412,7 +273,7 @@ static void testCreateTableHandler(std::string query,std::string db="tdb"){
my_gather_select
(
analysis
,
lex
);
auto
executor
=
my_rewrite_select
(
analysis
,
lex
);
QueryRewrite
*
qr
=
new
QueryRewrite
(
QueryRewrite
(
true
,
analysis
.
rmeta
,
analysis
.
kill_zone
,
executor
));
sp_next
(
db
,
query
,
qr
,
MygetResTypeFromLuaTable
(
true
));
sp_next
_first
(
db
,
query
,
qr
,
MygetResTypeFromLuaTable
(
true
));
}
int
...
...
@@ -431,7 +292,7 @@ main() {
globalConn
=
new
Connect
(
ci
.
server
,
ci
.
user
,
ci
.
passwd
,
ci
.
port
);
globalConn
->
execute
(
"use tdb"
);
ps
->
safeCreateEmbeddedTHD
();
std
::
string
query1
=
"select * from
child
;"
;
std
::
string
query1
=
"select * from
student
;"
;
std
::
vector
<
std
::
string
>
querys
{
query1
};
for
(
auto
item
:
querys
){
std
::
cout
<<
item
<<
std
::
endl
;
...
...
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