日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DataQL

發布時間:2023/12/16 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DataQL 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介

DataQL(Data Query Language)DataQL 是一種查詢語言。旨在通過提供直觀、靈活的語法來描述客戶端應用程序的數據需求和交互。

數據的存儲根據其業務形式通常是較為簡單的,并不適合直接在頁面上進行展示。因此開發頁面的前端工程師需要為此做大量的工作,這就是 DataQL 極力解決的問題。

請注意 DataQL 不是一門編程語言,它是查詢語言。它對邏輯的處理僅限于簡單場景。DataQL 的解決問題的重點集中在:數據的聚合和轉換以及過程中的簡單加工處理。

特性

  • 層次結構:多數產品都涉及數據的層次結構,為了保證結構的一致性 DataQL 結果也是分層的。
  • 數據為中心:前端工程是一個比較典型的場景,但是 DataQL 不局限于此(后端友好性)。
  • 弱類型定義:語言中不會要求聲明任何形式的類型結構。
  • 簡單邏輯:具備簡單邏輯處理能力:表達式計算、對象取值、條件分支、lambda和函數。
  • 編譯運行:查詢的執行是基于編譯結果的。
  • 混合語言:允許查詢中混合任意的其它語言代碼,典型的場景是查詢中混合 SQL 查詢語句。
  • 類 JS 語法:類JS語法設計,學習成本極低。
  • 語法手冊

    詞法記號
    • 注釋支持://、/*…*/

    • 支持任意空格,提高可讀性,支持\t,\n,\r,\f

    • 關鍵字:

      關鍵字含義
      if條件語句的引導詞
      else用在條件語句中,表明當條件不成立時的分支
      return三大退出指令之一,終止當前過程的執行并正常退出到上一個執行過程中
      throw三大退出指令之一,終止所有后續指令的執行并拋出異常
      exit三大退出指令之一,終止所有后續指令的執行并正常退出
      var執行一個查詢動作,并把查詢結果保存到臨時變量中
      run僅僅執行查詢動作,不保留查詢的結果
      hint寫在 DataQL 查詢語句的最前面,用于設置一些執行選項參數
      import將另外一個 DataQL 查詢導入并作為一個 Udf 形式存在、或直接導入一個 Udf 到當前查詢中
      as與 import 關鍵字配合使用,用作將導入的 Udf 命名為一個本地變量名
      true基礎類型之一,表示 Boolean 的:真值
      false基礎類型之一,表示 Boolean 的:假值
      null基礎類型之一,表示 NULL 值
    • 標識符:表示查詢中的一些實體,如變量名參數名。必須滿足正則表達式:[_a-zA-Z][_0-9a-zA-Z]*,一些對象的key可能會超出范圍,可以用反引號`xxx`。

    • 分隔符:()、{}、[]、,、:、;(非必須)

    • 運算符:

    • 數學運算:+,-,*,/,\(整除),%
    • 位運算:&,|,!,^(異或),<<(左位移),>>(有符號右位移),>>>(無符號右位移)
    • 比較運算:>,>=,<,<=,==,!=
    類型系統

    DataQL 是弱類型定義的查詢語言,在DataQL 中所有數據都會被歸結到有限的幾種類型上。無需定義數據類型結構,在弱類型系統中編寫查詢會非常方便,它去掉了繁雜的類型定義。

    數據類型表示方式詳情
    布爾truefalse表示真假值
    數值負無窮大0正無窮大浮點數、整數、科學計數法表示的數
    字符串’ 或 “字符串 或 單個字符
    空值nullNULL空值
    集合[…] 數組 或 多維數組帶有順序的多組數據的集合
    對象{‘key’:…} 具有鍵值對的數據體DataQL 的對象不支持方法,但是可以具備 Udf 類型的屬性。
    UDFlambda 函數 或 一個外部的 Udf一個外部的 net.hasor.dataql.Udf 接口函數定義。
    DataQL 中書寫的 lambda 函數也被稱作為 UDF。
    一個擴展代碼片段的定義,也屬于 UDF 的范疇。
    • 數值類型

      • 二進制表示法:0b010101011000B01010101100
      • 十進制表示法:0o12345670O1234567
      • 八進制表示法:-0000234123
      • 十六進制表示法:0x123450X12345
      • 科學計數法:a * 10的n 次冪的形式,其中 1 < a < 10
      • 關于負數:目前只有十進制表示法中提供了負數的表示能力。
    • UDF

      • 外部Udf:外部的 Udf 被引入之后,通常以標識符形式表示它。
      • DataQL 中書寫的 lambda 表達方式為:var foo = () -> { /* 代碼塊 */ }
      • 外部代碼片段:var a = @@xxx() <% /* 外部代碼塊 */ %>
    • JSON

      • DataQL 可以直接表達 Json 數據(Json 的 Key 必須通過雙引號或單引號形式包裹起來)
    • 當兩類型不匹配時能自動類型提升。

    數值
    • 支持:byte、short、int、long、float、double、BigInt、Decimal

    • 數值寬度默認是int和double

    • 浮點數計算時默認保留20位小數,多余的四舍五入。修改精度使用hint MAX_DECIMAL_DIGITS=20,更換舍入規則hint NUMBER_ROUNDING = 'HALF_EBEN'。

    語句
    • import

      • import “<函數類或函數包類>” as <別名>
      • import @"<資源地址>" as <別名>
      • 別名必須滿足 標識符
      • 必須放在整個查詢最開始的地方,被導入的資源會以var的方式定義。
    • var

      • var <變量名> = <表達式 or 值對象 or 函數定義>
      • 定義變量、執行并存儲表達式的值
    • run

      • run <表達式 or 值對象 or 函數定義>
    • return、throw、exit

      • return <狀態碼>, <表達式 or 值對象 or 函數定義>
      • 還可以不指定狀態碼
      • return <表達式 or 值對象 or 函數定義>
      • 三者除了行為不同,用法完全一樣。
    • if

      • 令DataQL變得靈活的存在

      • if` `(boolean_expression) {``/* 如果布爾表達式為真將執行的語句 */ } ``else` `{``/* 如果布爾表達式為假將執行的語句 */ }
    • hint

      • hint <選項名稱> = <選項值>
      • 作用是設置一些執行查詢使用的選項參數??梢詤⒖歼@里
    表達式
    • 一元運算:!(對Boolean取反),-(對數值取相反數)
    • 二元運算:主要是面向number,但是也支持字符串拼接。
    • 三元運算:testExpr ? expr1 : expr2
    訪問符
    • 取值域:

      • $:值域符A
      • #:值域符B
      • @:值域符C
      • 應用場景:1. 獲取程序傳來的參數。2. 表達式中的訪問符。
    • 獲取程序傳來的參數:<訪問符>{<參數名>} ,如${abc}

    • 表達式中的訪問符:$(環境棧根),#(環境棧頂),@(整個環境棧(數組形態))

      • DataQL 查詢過程中一般情況下環境棧始終是空的,當遇到 => 操作時。

        DataQL 會把 => 符左邊的表達式值放入環境棧,當轉換結束時 DataQL 會把表達式值從環境棧中刪掉。

        如果在轉換過程中遇到第二次 => 操作,那么會在環境棧頂中放入新的數據。

    取值與賦值
    • 對象取值:return userInfo.username;

    • 函數結果取值:return userByID({'id': 4}).username;

    • 數組中取值:return userList()[0].username;

    • 下標取值:return userInfo['username'];

    • 連續下標取值:return userList[0]['username'];

    • 數組下標取值:

      • 正向索引:list[3] = 3,
      • 反向索引:list[-3] = 7,
      • 索引溢出:三種處理方式:throw,null,near(默認)
    • 下標變量:使用變量代替下標

      // 定義一個變量,變量表示要取值的字段名。 var columnKey = 'username'; // 通過下標變量方式來取值 return userInfo[columnKey];
    • 賦值

      • 在DataQL中數據是不可被修改的只能重新生成數據集或者在結果轉換中對局部數據進行修改。
      • 重定義: 在任何時候都可以通過var來重新定義一個已經存在的變量。
    結果轉換
    • 結果轉換是DataQL的核心能力,可以大體歸納為:組裝(憑空構造)和變換。

    • 組裝:

      • case1:

        var userName = "馬三"; // 姓名 var userAge = 23; // 年齡// 返回一個對象數據,將用戶名稱和年齡組裝到一個對象中 return {"name" : userName,"age" : userAge };
      • case2:

        var data1 = 123; // 值1 var data2 = 456; // 值2// 返回2個元素的數組 return [data1, data2 ];
      • case3:

        var data = [123, 456];//它組裝了兩個字段。但是兩個字段分別來自于同一個數組數據的不同元素 return {"element_0" : data[0], // 123"element_1" : data[1] // 456 };
    • 數組的變換(是一個一個元素依次按照規則進行轉換的)

      //首先我們有一個對象數組 var data = [{"userID" : 1234567891,"age" : 31,"name" : "this is name1.","nick" : "my name is nick1.","sex" : "F","status" : true },{"userID" : 1234567892,"age" : 32,"name" : "this is name2.","nick" : "my name is nick2.","sex" : "F","status" : true },{"userID" : 1234567893,"age" : 33,"name" : "this is name3.","nick" : "my name is nick3.","sex" : "M","status" : true } ]
      • case1:

        //得到一個新的數據集,只包含name和age字段 return data => [{"name", "age"} ];
      • case2:

        //只包含name和age字段,同時修改一下字段名 return data => [{"userName" : name, // 取 name 字段的值作為 userName 的值"userAge" : age} ];
      • case3:

        //返回所有用戶名的列表,得到字符串數組 return data => [ name ];
      • case4:

        //將 一組值類型 變換成 一組對象 var data = ["馬三", "馬四"]; return data => [{"name" : # // 符號 "#" 表示在對每個元素進行轉換的過程中的那個元素本身。} ]; //得到的就是 [ {"name":"馬三"}, {"name":"馬四"} ]
      • case5:

        //為二維數組的每個值都加上一個字符串前綴 var data = [[1,2,3],[4,5,6],[7,8,9] ] return data => [# => [ // 在結果轉換中對當前元素進行二次轉換"值:" + #] ] //查詢結果: [["值:1","值:2","值:3"],["值:4","值:5","值:6"],["值:7","值:8","值:9"] ]
    • 對象的變換

      //首先我們有一個對象 var data = {"userID" : 1234567890,"age" : 31,"name" : "this is name.","nick" : "my name is nick.","sex" : "F","status" : true }
      • case1:

        //通過變換而非組裝的方式將其轉換為一個數組,內容是一個對象 return data => [ # ]; //---------結果--------- [{"userID": 1234567890,"age": 31,"name": "this is name.","nick": "my name is nick.","sex": "F","status": true} ]
      • case2:

        //對象的變換通常都是結構上的變化。對象可以是數組形式的一個元素,數組中可以疊加對象的變換 return data => {"name","info" : {"age","sex"} } //查詢結果 {"name": "this is name.","info": {"age": 31,"sex": "F"} }
    • 使用表達式

      • case1:

        //對結果變換過程中通過表達式來對字段重新計算 return data => {"name","age" : age + "歲","old" : age, // 這是有效的,age能夠使用多次"old" : name, // 這是無效的,"old"只會顯示上面那個"sex" : (sex == 'F') ? '男' : '女' }
    • 通過Lambda模擬for循環

      import 'net.hasor.dataql.fx.basic.CollectionUdfSource' as collect;var map = {"a" : 123,"b" : 321 } var data = [{"name" : "馬三","type" : "a"},{"name" : "n2","type" : "b"} ]var appendData = (dat) -> {//這個dat是data中的一個對象。lambda表達式只用處理一個元素即可,具體的整個數組的調用邏輯在return的時候。var newMap = collect.newMap(dat);run newMap.put('type',map[dat.type])//給這個newMap中設置'type'屬性,值是這樣取出來的(從map取出(key是(dat.type的value)的鍵值對)的值)。return newMap.data() };return data => [appendData(#) ] // 變量appendData定義為一個函數,這個函數有一個參數。 // 對data進行變換時,變換規則是之前定義的函數appendData, // 在這個函數中參數為當前data數組中的一個對象元素, // 所以在函數中是對一個對象進行操作,不用考慮數組的問題。 // 數組是在return的時候對person進行變換,對每個元素#調用定義的lambda函數appendData實現的。//執行結果 [{"name": "馬三","type": 123},{"name": "n2","type": 321} ]
    • Tips:

    • 變換要出現數組,則以[]包裹,對象則{}包裹,只有[]沒有{}的是字符串數組。在變換中能自由改名并使用表達式組合結果,并且可以一個元素多次使用,但是同名屬性只以第一次出現為準。
    • 對數組的循環操作可以通過,在return中對數組取#實現對每個元素的更改。
    函數
    • 定義函數:可以直接用DataQL語言定義一個函數,然后在后續查詢中使用它。

      var convertSex = (sex) -> {//定義一個函數return (sex == 'F') ? '男' : '女' };var data = {"userID" : 1234567890,"age" : 31,"name" : "this is name.","nick" : "my name is nick.","sex" : "F","status" : true };return data => {"name","age" : age + "歲","sex" : convertSex(sex)//使用函數得到值 }
    • 外部函數:DataQL具有官方標準函數庫,可以通過import語句導入。

      //通過時間函數庫獲取時間 import 'net.hasor.dataql.fx.basic.DateTimeUdfSource' as time;return time.now();//通過json函數庫來生成JSON數據 import 'net.hasor.dataql.fx.basic.JsonUdfSource' as json;return json.toJson([0,1,2])// "[0,1,2]"
      • 開發者還可以自己編寫函數(編寫UDF)
    • Lambda寫法

      import 'net.hasor.dataql.fx.basic.CollectionUdfSource' as collect; // 數據 var dataList = [{"name" : "馬一" , "age" : 18 },{"name" : "馬二" , "age" : 28 },{"name" : "馬三" , "age" : 30 },{"name" : "馬四" , "age" : 25 } ]//只保留年齡大于20歲的數據// 使用非Lambda的寫法---------------- // 年齡過濾邏輯 var filterAge = (dat) -> {return return dat.age > 20; }; // 調用 filter 函數 return collect.filter(dataList, filterAge);//使用Lambda的寫法----------------------省略了一個函數定義 var result = collect.filter(dataList, (dat) -> { // lambda 寫法return dat.age > 20;// 年齡過濾條件 });
    混合其他語言

    ? 在DataQL中混合其他語言一起協同處理DataQL查詢,需要定義一個片段執行器。

    • 典型的場景是把SQL語句混合在DataQL中。

      var dataSet = @@sql(item_code) <%select * from category where co_code = #{item_code} %>return dataSet() => [{ "id","name","code","body" } ] // @@sql 是 FunctionX 擴展包中提供的一組片段執行器,這個片段執行器相當于讓 DataQL 有能力執行數據庫的 SQL 語句。
    • 定義:定義一個片段執行器需要,實現 net.hasor.dataql.FragmentProcess 接口(更多信息請參考開發手冊)并且將其注冊到 DataQL 環境中

      // 方式一:通過Dataql接口 FragmentProcess process = ... AppContext = appContext = ...DataQL dataQL = appContext.getInstance(DataQL.class);//獲取 DataQL 接口 dataQL.addFragmentProcess("sql", process); //注冊片段執行器// 方式二:通過QueryModule FragmentProcess process = ...public class MyQueryModule implements QueryModule {public void loadModule(QueryApiBinder apiBinder) {dataQL.addFragmentProcess("sql", process); //注冊片段執行器} }
    • 使用:

      定義一個片段執行器需要使用 @@xxxx(arg1,arg2,arg3,…)<% … %> 語法,其中:

      • xxxx 為片段執行器注冊的名稱。
      • (arg1,arg2,arg3,…) 為執行這個代碼時傳入的參數列表。如果不需要定義任何參數可以是 ()
      • <%%> 之間編寫的是 目標語言的代碼片段。
      // 在 MySQL 中插入一條數據,并返回自增的ID var saveData = @@sql(data) <%insert into my_option (`key`,`value`,`desc`) values (#{data.key},#{data.value},#{data.desc});select LAST_INSERT_ID(); %> return saveData(${root});

    數據模型

    DataQL的數據模型是通過net.hasor.dataql.domain.DataModel接口表示的,共計4個實現類:ValueModel,ListModel,ObjectModel,UdfModel。

    還有一個非常重要的unwrap方法,能解除DataModel形態的封裝,直接變成Map/List結構,注意UdfModel類型解開是Udf接口。

    • ValueModel:用于表示String、Number、Boolean、Null四種基本數據類型。有isXxx()方法用于判斷類型,asXxx()方法用于獲取對應值。
    • ListModel:表示一個列表或集合的數據,相比較 DataModel 多了一組根據元素位置判斷對應類型的接口方法。
    • ObjectModel:表示一個列表或集合的數據,相比較 DataModel 多了一組根據元素 Key 判斷對應類型的接口方法。
    • UdfModel:當 DataQL 查詢返回一個 Udf 函數或者 Lambda 函數時,就會得到一個 UdfModel。而它事實上就是一個 Udf

    開發手冊

    執行查詢

    ? 引入依賴

    <dependency><groupId>net.hasor</groupId><artifactId>hasor-dataql</artifactId><version>4.2.1</version> </dependency>
  • 通過Hasor使用DataQL

    //由于 AppContext 有自身的聲明周期特性,因此需要做一個單例模式來創建 DataQL 接口。 public class DataQueryContext {private static AppContext appContext = null;private static DataQL dataQL = null;public static DataQL getDataQL() {if (appContext == null) {appContext = Hasor.create().build();dataQL = appContext.getInstance(DataQL.class);}return dataQL;} }//然后在Test中執行查詢 HashMap<String, Object> tempData = new HashMap<String, Object>() {{put("uid", "uid is 123");put("sid", "sid is 456"); }};DataQL dataQL = DataQueryContext.getDataQL(); Query dataQuery = dataQL.createQuery("return [${uid},${sid}]"); QueryResult queryResult = dataQuery.execute(tempData); DataModel dataModel = queryResult.getData(); List list = (List)dataModel.unwrap();for (Object o : list) {System.out.println(o);}
  • 通過JSR223使用DataQL:我這里略

  • 基于底層接口使用DataQL

    DataQL 的運行基于三個步驟:

    • 1.解析DataQL查詢:把 DataQL 查詢字符串通過解析器解碼為 AST(抽象語法樹)QueryModel queryModel = QueryHelper.queryParser(query1);
    • 2.編譯查詢:將DataQL 的 AST(抽象語法樹) 編譯為 QIL 指令序列。QIL qil = QueryHelper.queryCompiler(queryModel, ``null``, Finder.DEFAULT);
    • 3.執行查詢:最后在根據 QIL 創建對應的 Query 接口即可。Query dataQuery = QueryHelper.createQuery(qil, Finder.DEFAULT);
  • 查詢接口(Query)
    無論使用何種方式查詢都會通過DataQL的查詢接口發出查詢指令。

    查詢接口提供了三種不同參數類型的查詢重載,所有入參數最后都被轉換成為 Map 結構然后統一變換成為 CustomizeScope 數據域形式。

  • 查詢結果(QueryResult)

    發出DataQL查詢后,如果順利執行完查詢,結果會以QueryResult接口形式返回。

    /** 執行結果是否通過 EXIT 形式返回的 */ public boolean isExit();/** 獲得退出碼。如果未指定退出碼,則默認值為 0 */ public int getCode();/** 獲得返回值 */ public DataModel getData();/** 獲得本次執行耗時 */ public long executionTime();

    DataQL 的所有返回值都會包裝成 DataModel 接口類型。如果想拿到 Map/List 結構數據,只需要調用 unwrap 方法即可。

  • 全局變量

    添加全局變量有兩種方式:

  • 在QueryModule中初始化環節添加

    AppContext appContext = Hasor.create().build((QueryModule) apiBinder -> {apiBinder.addShareVarInstance("global_var", "g1"); });
  • 通過DataQL接口添加

    DataQL dataQL = appContext.getInstance(DataQL.class); dataQL.addShareVarInstance("global_var", "g2");
  • 獲取全局變量

    return global_var;
  • 函數
    • 開發Udf

      一個Udf必須是實現了net.hasor.dataql.Udf接口,注冊Udf的方式和添加全局變量相同。

      public class UserByIdUdf implements Udf {private UserManager userManager;public Object call(Hints readOnly, Object[] params) {return userManager.findById(params[0]);} }
    • 參數中的Udf

      DataQL 允許在執行查詢時通過參數形式提供 Udf ,這種方式傳入的 Udf 在調用時也需要使用 ${…} 來獲取

      HashMap<String, Object> tempData = new HashMap<String, Object>() {{put("findUserById", new UserByIdUdf()); }};AppContext appContext = Hasor.create().build(); DataQL dataQL = appContext.getInstance(DataQL.class);//得到 DataQL接口 Query dataQuery = dataQL.createQuery("return ${findUserById}(1) => { 'name','sex' }"); // 創建查詢 QueryResult queryResult = dataQuery.execute(tempData); DataModel dataModel = queryResult.getData();
    • 函數包(UdfSource)

      UdfSource 是一個函數包接口,接口中只有一個 getUdfResource 方法,用于返回函數包中的所有 Udf(Map形式返回)但是一般情況下更推薦使用 UdfSourceAssembly 接口。

      使用函數包的好處是可以像平常開發一樣編寫 Udf,無需考慮 Udf 接口的細節。裝配器會自動幫助進行參數和結果的轉換。

      public class DateTimeUdfSource implements UdfSourceAssembly {/** 返回當前時間戳 long 格式 */public long now() { ... }/** 返回當前系統時區的:年 */public int year(long time) { ... }/** 返回當前系統時區的:月 */public int month(long time) { ... }/** 返回當前系統時區的:日 */public int day(long time) { ... }... } // 最后在查詢中通過 <函數包名>.<函數> 的形式調用函數包。
    • inport導入(函數/函數包)

      如果 Classpath 中已經存在某個 Udf 類,還可以通過 import 語句導入使用。

      import 'net.xxxx.foo.udfs.UserByIdUdf' as findUserById; return findUserById(1) => { 'name','sex' };

      函數包的導入語句相同,只是在調用函數包中函數的時需要指明函數包

      import 'net.xxxx.foo.udfs.DateTimeUdfSource' as timeUtil; return timeUtil.now();
    • 使用注解批量注冊

      通過 @DimUdf 注解可以快速的聲明函數

      @DimUdf("findUserById") public class UserByIdUdf implements Udf {private UserManager userManager;public Object call(Hints readOnly, Object[] params) {return userManager.findById(params[0]);} }

      通過 @DimUdfSource 注解可以快速的聲明函數包:

      @DimUdfSource("time_util") public class DateTimeUdfSource implements UdfSourceAssembly {... }

      然后在初始化時掃描加載它們

      AppContext appContext = Hasor.create().build(apiBinder -> {QueryApiBinder queryBinder = apiBinder.tryCast(QueryApiBinder.class);queryBinder.loadUdf(queryBinder.findClass(DimUdf.class));queryBinder.loadUdfSource(queryBinder.findClass(DimUdfSource.class)); });
    外部代碼片段
    • 外部代碼執行器

      外部代碼片段是 DataQL 特有能力,它允許在 DataQL 查詢中混合其它語言的腳本。并將引入的外部語言腳本轉換為 Udf 形式進行調用。使用這一特性時需要擴展 FragmentProcess 接口,并注冊對應的外部代碼執行器。

      //外部代碼執行器,接收<% %>包裹的代碼,然后調用jdbcTemplate的query方法執行具體的SQL查詢 @DimFragment("sql") public class SqlQueryFragment implements FragmentProcess {@Injectprivate JdbcTemplate jdbcTemplate;public Object runFragment(Hints hint, Map<String, Object> paramMap, String fragmentString) throws Throwable {return this.jdbcTemplate.queryForList(fragmentString, paramMap);} }//在初始化階段注冊這個代碼執行器,就可以在查詢時使用了這個外部代碼片段了 public class MyFragment implements QueryModule {public void loadModule(QueryApiBinder apiBinder) {//掃描所有標記了@DimFragment注解的類并加載它apiBinder.loadFragment(queryBinder.findClass(DimFragment.class));} }//DataQL語句,通過@@指令開啟了一段外部代碼的定義,執行器的名字是sql var dataSet = @@sql(item_code) <%select * from category where co_code = #{item_code} %>return dataSet() => [{ "id","name","code","body" } ]
    • 資源加載器(Finder)

      資源加載器是net.hasor.dataql.FInder,其主要負責import語句導入資源/對象的加載。通常不會接觸到它。

      import ``'userBean'` `as ub;``//userBean 是 Bean 的名字 return` `ub().name;

    SQL執行器

    SQL 執行器是 DataQL 的一個 FragmentProcess 擴展,其作用是讓 DataQL 可以執行 SQL。執行器的實現是 FunctionX 擴展包提供的。使用執行器需要引入擴展包。

    <dependency><groupId>net.hasor</groupId><artifactId>hasor-dataql-fx</artifactId><version>4.2.1</version> </dependency>
    功能與特性
    • 支持兩種模式:簡單模式分頁模式
    • 簡單模式下,使用原生SQL。100% 兼容所有數據庫
    • 分頁模式下,自動改寫分頁SQL。并兼容多種數據庫
    • 支持參數化 SQL,更安全
    • 支持 SQL 注入,更靈活
    • 支持批量 CURD
    配置和方言
    • 配置數據源

      //普通方式配置數據源,在Hasor中初始化數據源即可 public class ExampleModule implements Module {public void loadModule(ApiBinder apiBinder) throws Throwable {// .創建數據源DataSource dataSource = null;// .初始化Hasor Jdbc 模塊,并配置數據源apiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));} }
    • 方言

      配置方言使用 hint HASOR_DATAQL_FX_PAGE_DIALECT = mysql,即可設置方言。支持Mysql,Oracle,SqlServer2012,PostgreSQL,DB2,Infomix。

    執行SQL
    • 執行SQL

      // 聲明一個 SQL var dataSet = @@sql() <%select * from category limit 10; %>// 執行這個 SQL,并返回結果 return dataSet();
    • SQL參數化

      // 聲明一個 SQL var dataSet = @@sql(itemCode) <%select * from category where co_code = #{itemCode} limit 10; %>// 執行這個 SQL,并返回結果 return dataSet(${itemCode});
    • SQL注入

      //SQL注入是為了一些特殊場景需要拼接SQL而準備的,如:動態排序字段和排序規則 // 使用 DataQL 拼接字符串 var orderBy = ${orderField} + " " + ${orderType};// 聲明一個可以注入的 SQL var dataSet = @@sql(itemCode,orderString) <%select * from category where co_code = #{itemCode} order by ${orderString} limit 10; %>// 執行這個 SQL,并返回結果 return dataSet(${itemCode}, orderBy);
    • Ognl表達式

      //同Mybatis一樣,SQL執行器可以將一個對象作為參數傳入 // 例子數據 var testData = {"name" : "馬三","age" : 26,"status" : 0 }// insert語句模版 var insertSQL = @@sql(userInfo) <%insert into user_info (name,age,status,create_time) values (#{userInfo.name},#{userInfo.age},#{userInfo.status},now()) %>// 插入數據 return insertSQL(testData);
    • 批量操作

      DataQL 的 SQL 執行器支持批量 Insert\Update\Delete\Select 操作,最常見的場景是批量插入數據。批量操作必須滿足下列幾點要求:

      • 入參必須是 List
      • 如果有多個入參。所有參數都必須是 List 并且長度必須一致。
      • @@sql()<% … %> 寫法升級為批量寫法 @@sql[]()<% … %>
      • 如果批量操作的 SQL 中存在 SQL注入,那么批量操作會自動退化為:循環遍歷模式
      • 由于批量操作底層執行SQL使用java.sql.Statement.executeBatch方法,因此insertSQL的返回值是int數組。
      // 例子數據 var testData = [{ "name" : "馬一", "age" : 26, "status" : 0 },{ "name" : "馬二", "age" : 26, "status" : 0 },{ "name" : "馬三", "age" : 26, "status" : 0 } ]// insert語句模版 var insertSQL = @@sql[](userInfo) <%insert into user_info (name,age,status,create_time) values (#{userInfo.name},#{userInfo.age},#{userInfo.status},now()) %>// 批量操作 return insertSQL(testData);
    • 執行結果拆包

      拆包是指將只返回一行一列的數據如count(*),拆解為int類型。

      有三種模式,默認為column

    • off:不拆包,嚴格返回一個對象數組。
    • row:最小粒度到行,多條記錄時正常返回,返回0或1條記錄時,返回一個Object。
    • column:最小粒度到列,當返回結果只有一行一列時,返回具體值。
    • 拆包模式可以通過hint改變,hint FRAGMENT_SQL_OPEN_PACKAGE = 'row'

      //hint FRAGMENT_SQL_OPEN_PACKAGE = "off" var dataSet = @@sql() <% select count(*) as cnt from category; %> var result = dataSet(); // 不指定 hint 的情況下,會返回 category 表的總記錄數,返回值為:10。 // 拆包模式變更為 row ,返回值為: { "cnt" : 10 } // 關閉拆包,返回值為標準的 List/Map: [ { "cnt" : 10 } ]
    • 結果列名拼寫轉換

      是指從數據庫查詢返回的列名信息,按照某一規則統一處理,如所有key轉為駝峰。可以使返回的列信息具有很高的可讀性。

      hint FRAGMENT_SQL_COLUMN_CASE = "hump"

      幾個可供配置的值:

      • default:保持原樣,這是個默認設置
      • upper:全部轉大寫
      • lower:全部轉小寫
      • hump:轉換成駝峰
    • 分頁查詢

      默認關閉,通過hint FRAGMENT_SQL_QUERY_BY_PAGE = true打開。

      打開分頁后經過3個步驟:

      • 定義分頁SQL
      • 創建分頁查詢對象
      • 設置分頁信息
      • 執行分頁查詢
      // SQL 執行器切換為分頁模式 hint FRAGMENT_SQL_QUERY_BY_PAGE = true// 定義查詢SQL var dataSet = @@sql() <%select * from category %>// 創建分頁查詢對象 var pageQuery = dataSet();//從數據庫查出來的是一個對象,有多種屬性,而不是僅有數據// 設置分頁信息 run pageQuery.setPageInfo({"pageSize" : 10, // 頁大小"currentPage" : 3 // 第3頁 });// 執行分頁查詢 var result = pageQuery.data(); // 獲取分頁信息 var info = pageQuery.pageInfo();

      由于大部分前端是以1為第一頁,而默認情況下SQL執行器是以0為第一頁的,所以需要-1,如果是GET方式發布的話,還需要使用轉換函數。

      import 'net.hasor.dataql.fx.basic.ConvertUdfSource' as convert; hint FRAGMENT_SQL_QUERY_BY_PAGE = true ... run queryPage.setPageInfo({"pageSize" : 5, // 頁大小"currentPage" : (convert.toInt(${pageNumber}) -1) });

      還有第二種方式,DataQL在4.1.8版本中加入FRAGMENT_SQL_QUERY_BY_PAGE_NUMBER_OFFSETHint,可以設置讓SQL執行器以1作為開始。

    • 數據庫事務

      SQL執行器本身并不支持事務,需要借助事務函數來實現。

      事務函數還可以嵌套使用。

      import 'net.hasor.dataql.fx.db.TransactionUdfSource' as tran; //引入事務函數 ... return tran.required(() -> {... // 事務return ... }); ...

      支持完整的7個傳播屬性:

      類型說明用法
      REQUIRED加入已有事務tran.required(() -> { … });
      REQUIRES_NEW獨立事務tran.requiresNew(() -> { … });
      NESTED嵌套事務tran.nested(() -> { … });
      SUPPORTS跟隨環境tran.supports(() -> { … });
      NOT_SUPPORTED非事務方式tran.notSupported(() -> { … });
      NEVER排除事務tran.never(() -> { … });
      MANDATORY要求環境中存在事務tran.tranMandatory(() -> { … });
    • 多數據源

      SQL執行器在4.1.4版本之后提供了通過hint來切換數據源的能力

      public class MyModule implements Module {public void loadModule(ApiBinder apiBinder) throws Throwable {DataSource defaultDs = ...;DataSource dsA = ...;DataSource dsB = ...;apiBinder.installModule(new JdbcModule(Level.Full, defaultDs)); // 默認數據源apiBinder.installModule(new JdbcModule(Level.Full, "ds_A", dsA)); // 數據源AapiBinder.installModule(new JdbcModule(Level.Full, "ds_B", dsB)); // 數據源B} } // 如果不設置 FRAGMENT_SQL_DATA_SOURCE 使用的是 defaultDs 數據源。 // - 設置值為 "ds_A" ,使用的是 dsA 數據源。 // - 設置值為 "ds_B" ,使用的是 dsB 數據源。 hint FRAGMENT_SQL_DATA_SOURCE = "ds_A"// 聲明一個 SQL var dataSet = @@sql() <% select * from category limit 10; %> // 使用 特定數據源來執行SQL。 return dataSet();
    • 多條查詢

      是指一次SQL執行的過程中,包含了一個以上的SQL語句。

      var dataSet = @@sql() <%set character_set_connection = 'utf8';select * from my_option; %>return dataSet(); // 默認返回最后一個SQL語句的結果。 // 可以通過 FRAGMENT_SQL_MUTIPLE_QUERIES hint來控制,例如:保留每一條結果。
    Mybatis執行器

    在4.1.8版本后加入了@@Mybatis執行器,這是對@@sql執行器的擴展,繼承了@@sql的能力,并提供了Mybatis的配置方式,提供了動態SQL的能力。

    • 對比@@sql的優勢

      • 繼承 @@sql 全部能力
      • 提供動態SQL能力,提供 SQL 層面的 if 和 for
      • 類似 mybatis 的工作方式,比起 DataQL 拼接字符串注入更加安全可靠。
      var dimSQL = @@mybatis(userName)<%<select>select * from user_info where `name` like concat('%',#{userName},'%') order by id asc</select> %>;
    • 提供的標簽

      • select

      • update

      • insert

      • delete

      • foreach:循環拼接SQL

        • collection:集合,必填
        • item:item,必填
        • open:起始,選填
        • close:結束,選填
        • separator:分隔符,選填
        <foreach collection="userIds.split(',')" item="userId" open="(" close=")" separator=",">#{userId} </foreach>
      • if:判斷條件,成立時拼接標簽內內容

        • test:判斷條件,必填
        <if test="userId != null and userId != ''">and user_id = #{userId} </if>

    FunctionX庫函數

    依賴:

    <dependency><groupId>net.hasor</groupId><artifactId>hasor-dataql-fx</artifactId><version>4.2.1</version> </dependency>
    轉換函數庫

    引入轉換函數庫:import 'net.hasor.dataql.fx.basic.ConvertUdfSource' as convert;

    • toInt(target):將Object轉換為Number,0x12->18,""->0,“abc”->throw error
    • toString(target):將Object轉換為String,null->“null”,[1,2,3,4]->"[1, 2, 3, 4]",{“test”:123}->"{test=123}"
    • toBoolean(target):將Object轉換為Boolean,支持on,off
    • byteToHex(target):將二進制數據轉換為十六進制字符串,將List<Byte>轉換為String。
    • hexToByte(target):將十六進制字符串轉換為二進制數據,將String轉換為List<Byte>
    • stringToByte(target, charset):將字符串轉換為二進制數據,將String轉換為List<Byte>,charset是String類型的字符集名稱,如’utf-8’
    • ByteToString(target, charset):將二進制數據轉換為字符串
    集合函數庫

    引入集合函數庫:import 'net.hasor.dataql.fx.basic.CollectionUdfSource' as collect;

    • isEmpty:注意:collect.isEmpty(null) = false// 不支持的基本類型會返回 false

    • size

    • merge:返回 List

    • mergeMap

    • filter(dataList, filterUDF):根據一個規則來對集合進行過濾。filterUDF類型:Udf/Lambda

      var result = collect.filter(dataList, (dat) -> {return dat.age > 20; });
    • filterMap(dataMap, keyFilterUDF)

    • limit(dataList, start, limit):截取List的一部分,返回一個List

    • newList

    • newMap(target):將一個map創建為帶狀態的Map,具有put(),putAll(),data(),size()方法

    • mapJoin(data_1,data_2,joinMapping):將兩個Map/List進行左連接,joinMaping是Map類型,表示兩表的join關系。

      import 'net.hasor.dataql.fx.basic.CollectionUdfSource' as collect;var year2019 = [{ "pt":2019, "item_code":"code_1", "sum_price":2234 },{ "pt":2019, "item_code":"code_2", "sum_price":234 },{ "pt":2019, "item_code":"code_3", "sum_price":12340 },{ "pt":2019, "item_code":"code_4", "sum_price":2344 } ]; var year2018 = [{ "pt":2018, "item_code":"code_1", "sum_price":1234.0 },{ "pt":2018, "item_code":"code_2", "sum_price":1234.0 },{ "pt":2018, "item_code":"code_3", "sum_price":1234.0 },{ "pt":2018, "item_code":"code_4", "sum_price":1234.0 } ];var result = collect.mapJoin(year2019,year2018, { "item_code":"item_code" }) => [{"商品Code": data1.item_code,"去年同期": data2.sum_price,"今年總額": data1.sum_price,"環比去年增長": ((data1.sum_price - data2.sum_price) / data2.sum_price * 100) + "%"} ] return result;
    • mapKeyToLowerCase:將Map的Key全部轉為小寫,如果Key沖突會產生覆蓋

    • mapKeyToUpperCase:將Map的Key全部轉為大寫,如果Key沖突會產生覆蓋

    • mapKeyToHumpCase:將Map的Key中下劃線轉為駝峰,如果Key沖突會產生覆蓋

    • mapKeys:提取Map的Key,返回List

    • mapValues:提取Map的Values,返回List

    • mapKeyReplace(dataMap, replaceKey):循環遍歷每一個Map元素,并對Map的Key進行替換,replaceKey是用于生成新key的函數。

      var data = {"key1":1, "key2":2, "key3":3 }; var result = collect.mapKeyReplace(data, (oldKey,value) -> {return "new_" + oldKey }); // result = {"new_key1":1, "new_key2":2, "new_key3":3 }
    • mapValueReplace:同上,不過是對值的處理

    • list2map(listData, dataKey, convertUDF):將List轉為Map,dataKey是鍵的名字,可以用字符串,也可以直接獲取,convertUDF是轉換的函數,可以不寫。

      //通過字符串指明Key字段 var yearData = [{ "pt":2018, "item_code":"code_1", "sum_price":12.0 },{ "pt":2018, "item_code":"code_2", "sum_price":23.0 },{ "pt":2018, "item_code":"code_3", "sum_price":34.0 },{ "pt":2018, "item_code":"code_4", "sum_price":45.0 } ];var result = collect.list2map(yearData, "item_code"); // result = { // "code_1": { "pt":2018, "item_code":"code_1", "sum_price":12.0 }, // "code_2": { "pt":2018, "item_code":"code_2", "sum_price":23.0 }, // "code_3": { "pt":2018, "item_code":"code_3", "sum_price":34.0 }, // "code_4": { "pt":2018, "item_code":"code_4", "sum_price":45.0 } // };//使用提取出來的值作為key var yearData = [ 1,2,3,4,5]; var result = collect.list2map(yearData, (idx,dat)-> {// Key 提取函數,直接把數組的數字元素內容作為 key 返回return dat; },(idx,dat) -> {// 構造 valuereturn { "index": idx, "value": dat }; });// result = { // "1": { "index": 0, "value": 1 }, // "2": { "index": 1, "value": 2 }, // "3": { "index": 2, "value": 3 }, // "4": { "index": 3, "value": 4 }, // "5": { "index": 4, "value": 5 } // }
    • map2list(dataMap, convert):將List轉換為Map,convert是轉換函數。

      // 不指定轉換函數 var data = {"key1":1, "key2":2, "key3":3 }; var result = collect.map2list(data); // result = [ // { "key": "key1", "value": 1}, // { "key": "key2", "value": 2}, // { "key": "key3", "value": 3} // ]// 指定轉換函數 var data = {"key1":1, "key2":2, "key3":3 }; var result = collect.map2list(data, (key,value) -> {return { "k" : key, "v" : value }; }); // result = [ // { "k": "key1", "v": 1}, // { "k": "key2", "v": 2}, // { "k": "key3", "v": 3} // ]
    • map2string(dataMap, joinStr, convert):將Map轉換成字符串,通常在生成Url參數時用到,joinStr表示連接符。

      var data = {"key1":1, "key2":2, "key3":3 }; var result = collect.map2string(data,"&",(key,value) -> {return key + "=" + value; }); // result = "key1=1&key2=2&key 3=3"
    • mapSort(dataMap, sortUdf):DataQL中的Map是有序的,因此可以排序。

    • listSort(dataList, sortUdf):對List進行排序

    • groupBy(dataList, groupByKey):根據公共字段對數據進行分組。groupByKey是String是要分組的字段名。數據集中需要有一個公共字段。

    • uniqueBy(dataList, uniqueByKey):根據公共字段去重,只返回第一次出現的。數據集中需要有一個公共字段。

    時間日歷函數庫

    引入函數庫:import 'net.hasor.dataql.fx.basic.DateTimeUdfSource' as time;

    • now:返回當前時間戳
    • year(time):返回時間戳中的年份,獲取當前年份:time.year(time.now())
    • month(time):返回時間戳中的月份。
    • day、dayOfMonth:返回時間戳中的日期是這個月的第幾天。
    • hour
    • minute
    • second
    • dayOfYear(time):返回時間戳中的日期是全年的第幾天。
    • dayOfWeek(time):返回時間戳中的日期是這周的第幾天,SUNDAY=1。
    • format(time, pattern):對時間戳進行時間日期格式化,底層使用的是java.text.SimpleDateFormat
    • parser(time, pattern):對時間按照格式進行解析,解析為時間戳。
    Json函數庫

    引入函數庫:import 'net.hasor.dataql.fx.basic.JsonUdfSource' as json;

    • toJson(target):返回String,把對象JSON序列化。
    • toFmtJson(target):返回String,把對象JSON序列化(帶格式)。
    • fromJson(jsonString):把JSON格式的字符串解析成對象。
    字符串函數庫

    引入函數庫:import 'net.hasor.dataql.fx.basic.StringUdfSource' as string;

    • startsWith(str, prifix):是否以xxx開頭
    • startsWithIgnoreCase
    • endsWith(str, prifix):是否以xxx結尾
    • endsWithIgnoreCase
    • lineToHump(str):下劃線轉駝峰
    • humpToLine
    • firstCharToUpperCase(str):首字母大寫
    • firstCharToLowerCase
    • toUpperCase
    • toLowerCase
    • indexOf(str, searchStr):查找第一次出現的位置
    • indexOfWithStart(str, searchStr, startPos):從某一位置開始,查找之后第一次出現的位置
    • indexOfIgnoreCase
    • indexOfIgnoreCaseWithStart
    • lastIndexOf
    • lastIndexOfWithStart
    • lastIndexOfIgnoreCase
    • lastIndexOfIgnoreCaseWithStart
    • contains(str, searchStr):是否包含字符串。
    • containsIgnoreCase
    • containsAny(str, searchStrArray):是否包含,指定List中的值。
    • containsAnyIgnoreCase
    • trim
    • sub(str, start, end):獲取指定位置的子串。
    • left(str, len):獲取最左邊的指定長度的串。
    • right
    • alignRight:右對齊,不足的向右填充
    • alignLeft
    • alignCenter
    • compareString:比較兩個字符串大小
    • compareStringIgnoreCase
    • split
    • join(array, separator):用separator將array拼裝成字符串
    • isEmpty
    • equalsIgnoreCase
    狀態函數庫

    引入函數庫:import 'net.hasor.dataql.fx.basic.StateUdfSource' as state;

    • decNumber(initValue):返回一個 Udf,每次調用這個 UDF,都會返回一個 Number。Number 值較上一次會自增 1。
    • incNumber(initValue):返回一個 Udf,每次調用這個 UDF,都會返回一個 Number。Number 值較上一次會自減 1。
    • uuid():返回一個完整格式的UUID字符串
    • uuidToShort():返回一個不含’-'的UUID字符串
    Web函數庫

    引入函數庫:import 'net.hasor.dataql.fx.web.WebUdfSource' as webData;

    • cookieMap
    • cookieArrayMap
    • getCookie
    • getCookieArray
    • tempCookie
    • tempCookieAll
    • storeCookie
    • removeCookie
    • headerMap
    • headerArrayMap
    • getHeader
    • getHeaderArray
    • setHeaderAll
    • addHeader
    • addHeaderAll
    • sessionKeys
    • getSession
    • setSession
    • removeSession
    • cleanSession
    • sessionInvalidate
    • sessionId
    • sessionLastAccessedTime
    簽名/編碼函數庫

    引入函數庫:import 'net.hasor.dataql.fx.encryt.CodecUdfSource' as codec;

    • encodeString
    • decodeString
    • encodeBytes
    • decodeBytes
    • urlEncode
    • urlEncodeBy
    • urlDecode
    • urlDecodeBy
    • digestBytes
    • digestString
    • hmacBytes
    • hmacString

    總結

    以上是生活随笔為你收集整理的DataQL的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    久久激情视频 | 亚洲视频高清 | 久久久香蕉视频 | 99精品视频在线播放观看 | 亚在线播放中文视频 | 亚洲电影图片小说 | 黄p在线播放 | 免费电影播放 | 午夜黄色 | 玖玖精品在线 | 国产在线观看午夜 | 久久精品久久99 | 亚洲免费在线观看视频 | 久久er99热精品一区二区三区 | 在线91网| 欧美日韩国产综合一区二区 | 国产亚洲欧美在线视频 | 日日躁夜夜躁xxxxaaaa | 激情伊人五月天 | 亚洲四虎在线 | 1024在线看片| 亚洲精品一区二区三区四区高清 | 91网在线 | 伊人夜夜 | 精品在线观| 免费看特级毛片 | 免费av在线网站 | 国产精品日韩在线播放 | 少妇视频在线播放 | 亚洲在线免费视频 | 国产精品福利av | 就操操久久 | 麻豆免费视频观看 | 91热这里只有精品 | 亚洲一级免费电影 | 日韩在线视频网 | 国产原创av在线 | 国产.精品.日韩.另类.中文.在线.播放 | 一区精品在线 | 97人人看| 伊人五月综合 | www.日日日.com| 日韩av电影中文字幕 | 免费av网站在线看 | 日韩视频在线不卡 | 久草在线中文视频 | 99 久久久久| 日韩免费在线视频 | 在线观看欧美成人 | 日日操天天操狠狠操 | 日日干夜夜操视频 | 91成人精品视频 | 久久视频免费观看 | 亚洲一级黄色av | 成人免费在线观看av | 国产精品不卡一区 | 成人av中文字幕 | 色综合网在线 | 亚洲午夜电影网 | 亚洲黄色三级 | 91av视频免费观看 | 91污污| 久久人人爽人人片av | 911av视频 | 超碰在线国产 | 成人免费视频网站 | 日本aaa在线观看 | 手机av在线网站 | 免费观看日韩 | 91精品在线视频 | 九九久久电影 | 欧美性久久久 | 欧美成人猛片 | 特级毛片在线观看 | 天天干天天拍天天操 | 欧美日韩亚洲在线 | 日本三级不卡 | 国产精品久久久久久久久久不蜜月 | 欧美激情精品 | 欧美精品三级在线观看 | 天天操操操操操操 | 97福利在线观看 | 天天操天天摸天天射 | 亚洲一区二区三区在线看 | 日日色综合 | 在线精品亚洲 | 中文在线最新版天堂 | 黄色中文字幕在线 | 午夜国产福利视频 | 国产精品久久久久久久久大全 | 日韩h在线观看 | 狠狠色丁香婷婷综合最新地址 | 99av国产精品欲麻豆 | 欧美日韩精品在线观看视频 | 婷婷资源站 | 久久精品一区二区国产 | 岛国大片免费视频 | 亚洲视频免费视频 | 高清av中文字幕 | 91精品在线视频观看 | 国产精品女人久久久 | 色在线最新 | 操老逼免费视频 | 精品一区二区电影 | 欧美日在线 | 日韩精品久久一区二区三区 | 成人av av在线 | 欧美淫视频 | 国模精品一区二区三区 | 亚洲国产成人av网 | 欧美另类z0zx| 亚洲一区视频在线播放 | a级国产乱理论片在线观看 特级毛片在线观看 | 中文国产字幕 | 成人蜜桃 | 在线免费观看成人 | 99r在线精品| 国产首页| 免费在线国产黄色 | 99久久精品免费视频 | 99精品视频在线看 | 久久久国产精品视频 | 午夜精品福利一区二区 | 国产综合在线观看视频 | 亚洲aⅴ久久精品 | 国产欧美日韩精品一区二区免费 | 亚洲一区免费在线 | 亚洲精品人人 | 成人免费视频网站在线观看 | 欧美一区二区三区特黄 | 日日激情 | 91中文字幕一区 | 亚洲国产精品va在线看 | 久保带人 | 午夜在线免费观看 | 精品国产免费av | 91成年人在线观看 | 天天摸天天舔天天操 | 久久久99精品免费观看 | 亚洲国产三级 | 五月综合色婷婷 | 青青五月天 | 日本特黄特色aaa大片免费 | 丁香六月久久综合狠狠色 | 亚洲精品久久激情国产片 | 91自拍视频在线 | 亚洲视频高清 | 天天天天天天天天操 | 午夜在线看片 | 一级片色播影院 | 99tvdz@gmail.com| 欧美日韩国产一二 | 久久精品欧美日韩精品 | 国产高清视频免费在线观看 | 韩国av电影网 | 亚洲欧美日韩一区二区三区在线观看 | 日日夜夜天天射 | 国产成人一区二区精品非洲 | 中文在线www | 成年美女黄网站色大片免费看 | 三级av在线免费观看 | 色综合久久综合网 | 国产成人免费观看久久久 | 久草视频免费播放 | 在线观看午夜 | 久久免费一级片 | 爱爱一区| 亚洲欧美国产精品va在线观看 | 欧美日韩视频在线观看一区二区 | 日韩在线视 | 国产精品美女久久久久久久久久久 | 99国产精品一区二区 | 一级精品视频在线观看宜春院 | 特级西西444www大精品视频免费看 | 一二三区视频在线 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 国产精品久久久久久69 | 国产激情电影综合在线看 | 九九免费在线看完整版 | 九九在线免费视频 | 午夜精品久久久久久久99无限制 | 免费精品国产va自在自线 | 国产视频在线观看一区二区 | av7777777 | 色狠狠久久av五月综合 | 亚洲午夜久久久久 | 日韩在线视 | 久久国产影院 | 深夜免费小视频 | 国产在线色站 | 国产精品久久久久影视 | 国产一级一片免费播放放 | 亚洲精品玖玖玖av在线看 | 激情av一区二区 | 国产精品成人久久久 | 国产美女黄网站免费 | 日韩三级一区 | 成人免费网站在线观看 | 国产精品久久久久久五月尺 | 久久久久久久久久久久久久av | 中文不卡视频 | 日韩视频www | 美女网站色在线观看 | 中文久草 | 成人免费大片黄在线播放 | 丁香婷婷在线 | 久草 | www视频在线观看 | 亚洲电影免费 | 亚洲免费av观看 | 国产99久久久久久免费看 | 国产成人黄色 | 成人av亚洲| 久久视频一区 | 国产精品视频全国免费观看 | 亚洲资源网 | 91久久偷偷做嫩草影院 | 在线91网 | 97视频久久久 | 日韩欧美在线观看 | 久热电影| 亚洲人成人99网站 | 在线亚洲成人 | 中文字幕123区 | 91麻豆看国产在线紧急地址 | 国产精品成久久久久 | 国产剧情av在线播放 | 精品国产一区二区三区久久久 | 日日夜夜天天 | 在线成人短视频 | 毛片基地黄久久久久久天堂 | 天天综合人人 | 全久久久久久久久久久电影 | 91视频这里只有精品 | 亚洲精品午夜久久久久久久久久久 | 丁香六月av | 婷婷在线视频 | 国产一级二级在线观看 | 久久久香蕉视频 | 91试看| 九九视频网站 | 国产婷婷色 | 激情喷水 | 麻豆精品国产传媒 | 国产在线色视频 | 久久这里有精品 | 欧美日韩在线免费观看 | 夜色资源网 | 在线播放av网址 | 麻花传媒mv免费观看 | 日韩小视频 | 久久视频这里有久久精品视频11 | 久久国产网 | 日韩欧美有码在线 | 亚洲视频免费在线看 | 亚洲免费永久精品国产 | 亚洲国产精品999 | 日韩a级免费视频 | 91成人精品观看 | 在线97| 国产成人精品久久 | av福利超碰网站 | 日韩精品一区二区三区中文字幕 | av日韩在线网站 | 国产亚洲aⅴaaaaaa毛片 | 成人av日韩 | 91精品国产自产老师啪 | 国产精品亚洲精品 | 国产一区二区在线播放 | av一区在线 | 91麻豆精品国产自产在线游戏 | 亚洲最快最全在线视频 | 免费看成人av | www免费| 九九视频精品免费 | 亚洲在线a | 国产一级视频在线观看 | 精品一区二区电影 | 精品福利网 | 中文字幕网址 | 日韩精品免费一区 | 久久免费视频7 | 91麻豆精品国产91久久久久久 | 久久久久久亚洲精品 | av日韩精品| 韩国精品一区二区三区六区色诱 | 天天透天天插 | 人人玩人人爽 | 日韩在线视频二区 | 超碰人在线 | 天天干天天干天天射 | a视频免费在线观看 | 亚洲精品影院在线观看 | 久久综合久久综合九色 | 五月天九九 | 亚洲欧美国产精品 | 91精品国自产在线 | 欧美性黑人 | 久久成人精品电影 | 国产亚洲精品久久久久久无几年桃 | 在线影院 国内精品 | 东方av在线免费观看 | 精品视频在线免费观看 | 在线播放 亚洲 | 欧美成年网站 | 午夜视频在线瓜伦 | 五月天亚洲综合 | 国产精品理论片在线观看 | 国产免费观看久久 | 欧美精品亚洲二区 | 毛片在线播放网址 | 国产 欧美 日本 | 97av视频| 黄色官网在线观看 | 日韩mv欧美mv国产精品 | 麻豆94tv免费版 | 欧美激情第28页 | www.在线看片.com | 国产一区二区在线观看视频 | 久草视频国产 | 久久久久久久久久免费 | 91传媒免费观看 | 九九热中文字幕 | 中文字幕第一页在线 | 国产丝袜美腿在线 | 久久久久久福利 | 天天激情天天干 | 菠萝菠萝在线精品视频 | 视频一区在线播放 | 精品国产免费人成在线观看 | 天天透天天插 | 999亚洲国产996395 | 中午字幕在线观看 | 欧美巨大荫蒂茸毛毛人妖 | 久草观看 | 午夜三级毛片 | 亚洲视频分类 | 午夜免费久久看 | 网址你懂的在线观看 | 久久精品一区二区国产 | www.久久精品视频 | 日韩中文久久 | 久久精品一区二 | 在线播放国产一区二区三区 | 在线观看的av网站 | 日韩av电影手机在线观看 | 久久av免费观看 | 成人精品久久久 | 久人人| 日日爽日日操 | 久久视频免费在线观看 | 99中文字幕 | 91亚洲精品久久久蜜桃网站 | 麻豆视频在线看 | 人人网av | 免费一级特黄录像 | adn—256中文在线观看 | 日韩av电影中文字幕在线观看 | 97狠狠操| 黄色av电影免费观看 | 日韩高清久久 | 丁香六月天 | 亚洲另类在线视频 | 黄色毛片一级片 | 久久999久久 | 国产看片 色 | 激情久久综合 | 久久精品欧美日韩精品 | 国产精品视频地址 | 字幕网在线观看 | 日韩最新理论电影 | 69久久久久久久 | 免费日韩 精品中文字幕视频在线 | 天天操操操操操操 | 久久久久国产成人免费精品免费 | 国产精品av久久久久久无 | 久久99国产视频 | 九九视频在线观看视频6 | 久久不射电影院 | 视频91 | 亚洲电影网站 | 国产精品成人一区二区 | 在线观看免费版高清版 | 国产视频欧美视频 | 人人爽影院 | 久久久www成人免费毛片麻豆 | 一区二区三区四区精品 | 午夜aaaa | 国产一区欧美日韩 | 91日韩在线专区 | 91资源在线观看 | 天天久久夜夜 | 在线视频18在线视频4k | 亚洲春色奇米影视 | 日韩午夜电影网 | 一区 二区电影免费在线观看 | 中文字幕一区二区在线观看 | 亚洲精品高清在线观看 | 丝袜美腿av| 日韩精品久久久久久 | 在线免费观看视频 | 久久免费视频在线 | 国产成人一区二区啪在线观看 | 国产片免费在线观看视频 | 亚洲成av人片在线观看www | 友田真希av| 亚洲伦理中文字幕 | 青青河边草免费观看 | 亚洲午夜久久久久久久久久久 | 又湿又紧又大又爽a视频国产 | 亚洲精品99久久久久中文字幕 | 久久精品99久久久久久2456 | 中文字幕精品一区二区精品 | 久久亚洲专区 | 色99久久| 久久精品黄 | 五月婷婷综合在线观看 | 天天操综合| 婷色在线| 最近中文字幕完整高清 | 久久99久久99精品免观看软件 | 久热免费 | 99精品欧美一区二区三区黑人哦 | 日韩在线观看精品 | 深夜免费福利网站 | 欧美精品在线免费 | 在线视频欧美日韩 | 国产成人黄色在线 | 国产明星视频三级a三级点| 日韩在线电影一区 | 精品极品在线 | 在线欧美a| 99视频网站 | 欧美性受极品xxxx喷水 | 成人免费视频视频在线观看 免费 | 国产精品入口66mio女同 | 久草精品视频在线播放 | 婷婷视频导航 | 97av影院| 狠狠操狠狠干天天操 | 美女网站视频久久 | 一区二区三区免费在线观看 | 精品国产综合区久久久久久 | 久久精品理论 | 精品国产免费一区二区三区五区 | 成人免费精品 | 日韩高清在线观看 | 久久久国产毛片 | 日韩一区二区三区高清免费看看 | av中文国产 | 国产免费久久精品 | a级国产乱理论片在线观看 伊人宗合网 | 91av视频免费在线观看 | 亚洲成av人影片在线观看 | 国产福利一区二区在线 | 久久少妇| 天天操欧美| 丁香综合| 国产午夜在线 | 免费观看完整版无人区 | 国产 精品 资源 | 欧美 亚洲 另类 激情 另类 | 日韩在线精品视频 | 91精品视频免费观看 | 女人18毛片a级毛片一区二区 | 日韩视频 一区 | 国产录像在线观看 | 99色在线播放 | 亚洲成人中文在线 | 亚洲性少妇性猛交wwww乱大交 | 久久99久久99免费视频 | 国内精品福利视频 | av电影中文| 免费观看的黄色 | 免费看三级黄色片 | 激情视频在线观看网址 | 亚洲一区二区视频在线播放 | 欧美日韩久久不卡 | 久香蕉| 中文字幕久久精品亚洲乱码 | 天天操天天艹 | 亚洲精品成人av在线 | 黄色网址av | 国产在线精品国自产拍影院 | 在线视频日韩 | 玖玖精品在线 | 日韩精品在线免费播放 | bbbb操bbbb| 91精品导航 | 久久久国产精品网站 | 国产黄色av影视 | 不卡的av电影 | 国产视频精品久久 | 99精品国产视频 | 九九免费在线观看视频 | 911精品视频| 久二影院 | 日本久久久亚洲精品 | 天天·日日日干 | 久久久精选 | 麻豆视传媒官网免费观看 | 国产不卡视频在线 | 亚洲在线资源 | 色操插| 国产视频久久久久 | 久久久久成人精品 | 欧美亚洲精品在线观看 | 国产在线播放一区 | 国产精品午夜久久 | 欧美在线视频一区二区三区 | 操少妇视频 | 91av原创 | 99热最新网址 | 99久久久成人国产精品 | 九九久久影视 | 91丨九色丨蝌蚪丨对白 | www.av小说| 久草在线视频国产 | 日韩 国产 | 91人人澡人人爽 | 99精品系列 | 国产一级片免费播放 | www.天天射.com| 偷拍区另类综合在线 | 永久av免费在线观看 | 国产精品久久久久久久久婷婷 | 国产精品久久99精品毛片三a | 国产网红在线观看 | 日本久久视频 | 丁香花中文字幕 | 91精品一区二区三区蜜臀 | 久久久久久免费毛片精品 | 中文字幕一区二区三区乱码在线 | 成人一级片在线观看 | 国内99视频 | 亚洲国产69 | 亚洲久久视频 | 国产精品专区在线 | 3d黄动漫免费看 | 国产精品一区二区精品视频免费看 | 看毛片网站 | 亚洲九九爱| 五月婷婷六月综合 | 国产系列 在线观看 | 久久久久久久久久久久电影 | 欧美综合久久 | 在线国产激情视频 | 久久精品视频日本 | 亚洲经典在线 | 精品99999| 天天草综合网 | 97久久久免费福利网址 | 久草在在线视频 | 亚洲资源一区 | 亚洲精品美女久久17c | 97色狠狠| 国产在线播放不卡 | 蜜桃视频在线视频 | 黄色激情网址 | 亚洲精品国偷拍自产在线观看蜜桃 | 久久九九免费视频 | 在线观看爱爱视频 | 欧美日韩不卡一区 | 久久久久久久久亚洲精品 | 欧美日韩在线视频观看 | 欧美日韩高清一区二区 国产亚洲免费看 | 五月婷婷激情六月 | 十八岁免进欧美 | 亚洲人成免费网站 | 精品女同一区二区三区在线观看 | 国产精品99久久久 | 成人午夜电影在线 | 免费在线观看日韩欧美 | 中文字幕在线免费播放 | 五月婷婷六月丁香在线观看 | 日韩av手机在线观看 | 国产成年免费视频 | 国产中文字幕在线观看 | 4p变态网欧美系列 | 日韩午夜高清 | 又粗又长又大又爽又黄少妇毛片 | 久久久久久免费毛片精品 | 亚洲综合最新在线 | 精品日韩在线一区 | 999成人 | 亚洲闷骚少妇在线观看网站 | 精品国产一区二区三区久久影院 | 久久久综合九色合综国产精品 | 亚洲国产97在线精品一区 | 中文在线8新资源库 | 日韩大片在线观看 | 久久99亚洲热视 | 久久影视网 | 天天操天天干天天干 | 青青草国产成人99久久 | 在线观看国产v片 | 久久精品国产亚洲 | 免费观看91视频 | 中文字幕av一区二区三区四区 | 92av视频| 天天夜操 | 久久精品亚洲一区二区三区观看模式 | 在线观看一区视频 | 婷婷色综合色 | 成年人视频免费在线 | 开心丁香婷婷深爱五月 | a天堂最新版中文在线地址 久久99久久精品国产 | 国产精品国产三级国产不产一地 | 毛片网在线观看 | 久草在线费播放视频 | 国产成人在线看 | 亚洲久草视频 | 国产婷婷 | 蜜臀av.com | 悠悠av资源片 | 国产成人精品日本亚洲999 | 国产成人黄色网址 | 天天操,夜夜操 | 91麻豆文化传媒在线观看 | 少妇搡bbbb搡bbb搡aa | 美女亚洲精品 | 久久99精品久久久久久清纯直播 | 99热这里只有精品久久 | 久久久久久精 | 在线精品视频免费播放 | 欧美亚洲三级 | 国产精品午夜在线观看 | 99精品久久只有精品 | 欧美一级特黄高清视频 | jizz欧美性9| 亚洲欧洲中文日韩久久av乱码 | 免费黄色小网站 | 国产黄 | 亚洲精品456在线播放乱码 | 久久久噜噜噜久久久 | 精品专区一区二区 | 亚洲网站在线 | 久久精品xxx | 欧美aaaxxxx做受视频 | 亚洲日本色 | 99视频精品 | 草久在线播放 | 欧美日韩成人 | 亚洲h色精品 | 亚洲天堂香蕉 | 国产精品久久99精品毛片三a | 狠狠操精品 | 97色se| 日韩伦理片一区二区三区 | 综合网伊人 | 欧美天天射 | 国产亚洲成av片在线观看 | 日韩在线不卡av | 九九免费精品 | 中文字幕在线视频一区二区三区 | 96精品在线 | 久久综合色综合88 | 国产高清视频免费最新在线 | 亚洲视频,欧洲视频 | 色94色欧美| 国产九九在线 | 久久精品视频网 | 国产精品网红直播 | 在线观看国产区 | 亚洲jizzjizz日本少妇 | 91九色国产 | 伊人夜夜 | 四虎免费在线观看 | 97在线看 | 国产黄在线看 | 欧美性生交大片免网 | 九九九免费视频 | 麻花豆传媒mv在线观看 | 国产精品免费久久久久久 | 国产亚洲精品久久久久秋 | 黄色aaa毛片| 尤物九九久久国产精品的分类 | 日本中文字幕视频 | www好男人| 日本九九视频 | 亚洲精品在线观看网站 | 最近更新好看的中文字幕 | 久久精品成人 | 久草在线91 | 五月婷婷操| www.91成人 | zzijzzij日本成熟少妇 | 婷婷色综合色 | 黄色毛片视频免费观看中文 | 97视频资源 | 超碰97av在线| 日日夜夜中文字幕 | 91麻豆精品国产自产在线游戏 | 黄色成人在线观看 | 黄色1级毛片| 精品国产123 | 久久免费看 | 久久久色| 天天操天天干天天插 | 九九免费精品视频在线观看 | 99久热在线精品 | 国内少妇自拍视频一区 | 在线播放av网址 | 国产精品久久久久久久av电影 | 91精品啪在线观看国产 | 欧美日一级片 | 伊人国产视频 | 免费成人在线观看视频 | 国产色婷婷在线 | 色午夜| 99精品视频在线观看免费 | 亚洲1区在线 | 久久久精品国产一区二区 | 国产中文在线字幕 | 国产成人99久久亚洲综合精品 | 免费精品在线视频 | 亚洲黄色a| 狠狠色噜噜狠狠 | 激情欧美一区二区三区免费看 | 天天综合入口 | 久久久久欠精品国产毛片国产毛生 | 成人免费观看完整版电影 | 在线高清 | 精品一区二区影视 | 欧美人牲 | 国产精品免费在线播放 | a在线观看免费视频 | 欧美成年黄网站色视频 | 黄色精品一区 | 色小说在线 | 在线欧美小视频 | 国产精品不卡在线播放 | 成人av教育 | 五月激情久久 | 国产色啪| 一本色道久久综合亚洲二区三区 | 亚洲 成人 一区 | 免费观看www视频 | 亚洲,国产成人av | 手机看片中文字幕 | 国产福利网站 | 香蕉免费| 九热精品| 久久久久久高清 | 久久夜色精品国产欧美一区麻豆 | 区一区二区三区中文字幕 | 全久久久久久久久久久电影 | 久久免费视频2 | 最新色站 | 国语对白少妇爽91 | 午夜av免费在线观看 | 日韩激情综合 | 国产精品久久99 | 精品欧美小视频在线观看 | 成人影片在线免费观看 | 中文在线www | 美女视频永久黄网站免费观看国产 | 91精品对白一区国产伦 | 香蕉视频在线网站 | 97理论片 | 黄色免费视频在线观看 | 91在线中文| 91免费国产在线观看 | 久草新在线 | 人人藻人人澡人人爽 | 免费日韩在线 | 欧洲一区精品 | 午夜av电影| www.亚洲| 精品久久久一区二区 | 91精品国| 福利一区二区 | av电影 一区二区 | 欧美日韩1区 | 亚洲日本三级 | 在线免费av网| 99热亚洲精品 | 欧美在线视频一区二区三区 | 国产精品麻豆视频 | 国产最新在线 | 极品美女被弄高潮视频网站 | 久久久久久久久久网 | 国产资源在线观看 | 五月婷婷六月丁香在线观看 | 亚洲精品麻豆视频 | 91在线看免费 | 久久99精品国产 | 亚洲精品视频在线观看免费视频 | 超碰日韩在线 | 深爱激情av | 欧美日韩国产精品一区二区亚洲 | 久视频在线播放 | ,午夜性刺激免费看视频 | 天天操网址| 欧美精品乱码久久久久久按摩 | 99久久精品免费 | 日本99热 | 亚洲精品乱码久久久久 | 国产福利精品视频 | 99视频在线 | 激情综合网色播五月 | 黄色91在线观看 | 免费看三级黄色片 | 久久久久久久久久久高潮一区二区 | 婷婷丁香国产 | 天堂v中文 | 日韩欧美视频免费观看 | 中文字幕av电影下载 | 免费a级大片 | 久久精品96| 五月婷婷六月丁香在线观看 | 日日爱影视 | 久久精品国产99国产 | 国产免费嫩草影院 | 蜜桃av综合网 | 久久伊人国产精品 | 香蕉视频在线看 | 国产日韩视频在线观看 | 久久国产亚洲精品 | 久久精品视频2 | 国产在线专区 | 成人一级视频在线观看 | 欧美日韩不卡在线观看 | 国产成人精品午夜在线播放 | 国产 在线观看 | 国产黄色片一级三级 | 99r在线| 久久精品99北条麻妃 | 亚洲精品黄网站 | 丁香六月天婷婷 | 91精品国产网站 | 日韩三级一区 | 亚洲成人网在线 | 亚洲a免费 | 欧美少妇影院 | av在线亚洲天堂 | 午夜色大片在线观看 | 亚洲综合少妇 | 日日日视频 | www91在线 | 欧美粗又大 | 日韩理论在线视频 | 91秒拍国产福利一区 | 成人免费视频播放 | 久久 精品一区 | 午夜精品久久久久99热app | 精品免费观看视频 | 欧美视频日韩视频 | 操处女逼| 91视频免费看片 | 欧美久久久久久久久久 | 色网av| 91一区啪爱嗯打偷拍欧美 | 最新色站| 精品一区在线看 | 麻豆视频免费入口 | 国产精品婷婷午夜在线观看 | 亚洲国产精品视频在线观看 | 亚洲一级片av | 中文字幕资源在线 | 黄色小说视频网站 | 色网址99 | 欧美日韩不卡在线 | 9999免费视频 | 成人网页在线免费观看 | 一区二区激情视频 | 日韩精品视频在线免费观看 | 91片在线观看 | 黄色av网站在线免费观看 | 中文字幕人成不卡一区 | 综合久久久久久久久 | 日韩精品一区二区不卡 | 国产一级视屏 | 中文字幕在线观看资源 | 国产精品白浆 | 国产成人福利 | 啪嗒啪嗒免费观看完整版 | 日日干美女 | 天天插天天狠天天透 | www.色就是色| 日韩电影中文 | 日韩大片在线 | 中文字幕韩在线第一页 | 亚洲国内精品在线 | 国产在线精品一区二区三区 | 久久久久久久久久网站 | 精品爱爱| 久久精品综合一区 | 日本高清xxxx | 99久视频 | 国产高清不卡一区二区三区 | 色视频在线免费 | 久久99精品久久久久久清纯直播 | 夜夜嗨av色一区二区不卡 | 免费亚洲一区二区 | 日韩欧美中文 | 国产精品 国内视频 | 在线观看日韩视频 | 国产精品永久久久久久久www | 亚洲经典精品 | 玖玖色在线观看 | 亚欧日韩成人h片 | 毛片黄色一级 | 手机av在线网站 | 99精品免费视频 | 国产精品自产拍在线观看桃花 | 国产欧美久久久精品影院 | 最近更新好看的中文字幕 | 免费观看视频黄 | 国产中文字幕在线视频 | 国产精品一级在线 | 欧洲一区二区在线观看 | av黄色亚洲 | 免费网站在线观看人 | 99久久这里只有精品 | 亚洲欧美视频在线播放 | av免费观看高清 | 在线免费黄色 | 久久国产精品第一页 | 色狠狠婷婷 | 日韩中文字幕国产精品 | 色婷婷色| 日本在线h | 国产在线一区二区 | 国产黄色特级片 | 国产伦精品一区二区三区照片91 | 久久国产精品第一页 | 亚洲视频h| 久久精品国产一区二区三 | 中文字幕在线观看网站 | 玖玖视频免费在线 | 色综合天天色综合 | 日韩一区二区三区视频在线 | 色婷婷午夜 | av成人黄色 | 国产亚洲婷婷免费 | 中文字幕网站视频在线 | www.五月天色 | 亚洲精品自拍 | 国产免费xvideos视频入口 | 九九色网 | 贫乳av女优大全 | 天天操天天弄 | 午夜视频在线观看一区二区三区 | 韩国在线视频一区 | 国产精品99久久久久久武松影视 | 久久久久亚洲精品中文字幕 | 天天色天天上天天操 | 国产高h视频 | 国产欧美精品在线观看 | 国产高清av在线播放 | 丁香国产视频 | 国产美腿白丝袜足在线av | 国产精品精品国产 | 999视频在线观看 | 日本成人a| 欧美日韩视频一区二区三区 | 成人av影视观看 | 亚洲综合成人在线 | 久久精品久久精品久久39 | 久久网页 | 91丨九色丨勾搭 | 欧美精品中文 | 国产精品午夜免费福利视频 | 在线视频观看国产 | 精品久久国产精品 | 九九九视频精品 | 日本黄色免费看 | 久久精品1区2区 | 国产免费观看视频 | 国产色在线| 一级久久精品 | a视频免费 | 国产资源免费在线观看 | 中文字幕观看在线 | 久章草在线观看 | 色综合久久88色综合天天免费 | 日日夜夜噜 | 久久不射电影院 | av在线播放快速免费阴 | 国产精品九九九 | 人人澡人人爽 | 午夜av电影院 | 亚洲人成人99网站 | 在线视频手机国产 | 久久少妇av | 天天操天天色天天射 | 久久久18 | 成人在线视频网 | 天天做日日爱夜夜爽 | 国产一区二区高清 | av三级在线免费观看 | 在线观看爱爱视频 | 99这里有精品 | 在线成人一区二区 | 一级黄色片在线观看 | 欧美日韩不卡一区二区三区 | 美腿丝袜av |