{"id":5609,"date":"2018-08-16T15:58:14","date_gmt":"2018-08-16T22:58:14","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=5609"},"modified":"2018-08-17T15:17:49","modified_gmt":"2018-08-17T22:17:49","slug":"testing-ansi-joins","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/testing-ansi-joins\/","title":{"rendered":"Pruebas de ANSI JOIN"},"content":{"rendered":"<h3><span style=\"font-weight: 400\">Visi\u00f3n general<\/span><\/h3>\n<p><span style=\"font-weight: 400\">El objetivo principal de este art\u00edculo es mostrar c\u00f3mo se prueban los ANSI JOINs de Couchbase. En <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/es\/announcing-couchbase-server-5-5\/\"><span style=\"font-weight: 400\">Couchbase versi\u00f3n 5.5<\/span><\/a><span style=\"font-weight: 400\">ahora puede ejecutar uniones utilizando la sintaxis est\u00e1ndar ANSI. Esta adici\u00f3n a las uniones las hace mucho m\u00e1s flexibles, pero tambi\u00e9n mucho m\u00e1s complejas. Esta complejidad hace que sea dif\u00edcil para nosotros probar en nuestro marco normal, simplemente hay demasiadas posibilidades para escribir manualmente para la automatizaci\u00f3n. Por suerte, uno de nuestros marcos de pruebas nos permite establecer los par\u00e1metros de una consulta y, a continuaci\u00f3n, genera conjuntos aleatorios de consultas basados en esos par\u00e1metros. Este marco se conoce como <\/span><b>Generador de consultas aleatorias (RQG)<\/b><span style=\"font-weight: 400\">. En este art\u00edculo discutiremos como RQG es usado para probar la funcionalidad ANSI JOIN que fue implementada. En primer lugar, vamos a echar un breve vistazo a lo que es diferente con ANSI JOINs.<\/span><\/p>\n<p><span style=\"font-weight: 400\">En este art\u00edculo repasaremos los siguientes temas:<\/span><\/p>\n<p style=\"padding-left: 30px\"><strong>1. Introducci\u00f3n a los JOIN ANSI <\/strong><\/p>\n<p style=\"padding-left: 30px\"><strong>2. Visi\u00f3n general del generador de consultas aleatorias (RQG) <\/strong><\/p>\n<p style=\"padding-left: 30px\"><strong>3. USO DE RQG para probar ANSI JOINs <\/strong><\/p>\n<p style=\"padding-left: 30px\"><strong>4. Puntos clave<\/strong><\/p>\n<p style=\"padding-left: 30px\"><strong>5. Lista de errores adicionales encontrados en ANSI JOIN<\/strong><\/p>\n<p style=\"padding-left: 30px\"><strong>6. Anexo<\/strong><\/p>\n<h3><span style=\"font-weight: 400\">Introducci\u00f3n a los JOIN ANSI <\/span><\/h3>\n<p><span style=\"font-weight: 400\">Anteriormente en Couchbase s\u00f3lo se pod\u00edan ejecutar lookup joins y <\/span><a href=\"https:\/\/dzone.com\/articles\/join-faster-with-couchbase-index-joins\"><span style=\"font-weight: 400\">uniones de \u00edndices<\/span><\/a><span style=\"font-weight: 400\">. Esto era bueno para las consultas en las que un lado de la uni\u00f3n puede producir una clave de documento del otro lado de la uni\u00f3n. Sin embargo, el problema con esto es que las uniones no pod\u00edan ejecutarse en otros campos de un espacio de claves. Las uniones ANSI solucionan este problema y lo llevan un paso m\u00e1s all\u00e1, ahora las uniones se pueden ejecutar en campos arbitrarios o expresiones que dan como resultado campos, o en m\u00faltiples condiciones de uni\u00f3n.<\/span><\/p>\n<p><b>Sintaxis antigua de Join:<\/b><\/p>\n<p style=\"text-align: center\"><span style=\"font-weight: 400\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span> <span style=\"font-weight: 400\">Lhs-keyspace [join-type] JOIN rhs-keyspace<\/span><\/p>\n<p style=\"text-align: center\"><span style=\"font-weight: 400\">ON KEYS [expresi\u00f3n que da como resultado un meta().id de uno de los espacios de claves].<\/span><\/p>\n<p><b>Sintaxis ANSI JOIN:<\/b><\/p>\n<p style=\"text-align: center\"><span style=\"font-weight: 400\">lhs-expresi\u00f3n [join-tipo] JOIN rhs-espacio-clave ON [join-condici\u00f3n].<\/span><\/p>\n<p><b>Consulta de sintaxis de uni\u00f3n antigua:<\/b><\/p>\n<pre class=\"wrap:true lang:default decode:true\">SELECT t_3.decimal_field1 , t_3.primary_key_id , t_3.varchar_field1 , t_3.char_field1 \r\nFROM multiple_table_db_87317526_simple_table_4 t_2 \r\nLEFT JOIN multiple_table_db_87317526_simple_table_1 t_3 \r\nON KEYS [ t_2.primary_key_id ]\r\nWHERE (t_2.bool_field1 != true AND t_3.decimal_field1 &lt;= 4980)<\/pre>\n<p><b>Misma consulta con ANSI JOINs Sintaxis:<\/b><\/p>\n<pre class=\"wrap:true lang:default decode:true\">SELECT t_3.decimal_field1 , t_3.primary_key_id , t_3.varchar_field1 , t_3.char_field1\r\nFROM multiple_table_db_87317526_simple_table_4 t_2 \r\nLEFT JOIN multiple_table_db_87317526_simple_table_1 t_3 \r\nON t_2.primary_key_id = t_3.primary_key_id\r\nWHERE (t_2.bool_field1 != true AND t_3.decimal_field1 &lt;= 4980)<\/pre>\n<p><span style=\"font-weight: 400\">Los tipos de join soportados en N1QL son INNER JOIN o LEFT\/RIGHT OUTER JOIN. Si simplemente pone JOIN se interpretar\u00e1 como INNER JOIN, y LEFT\/RIGHT JOIN se interpretar\u00e1 como OUTER JOIN. En la nueva sintaxis de join, el lado izquierdo del join puede ser un espacio clave, una consulta n1ql anidada, una expresi\u00f3n n1ql o un join propiamente dicho. El lado derecho del join debe ser un keyspace en la implementaci\u00f3n actual de ANSI JOINs dentro de Couchbase. La cl\u00e1usula ON contiene las condiciones que la uni\u00f3n debe cumplir, estas condiciones pueden ser cualquier expresi\u00f3n predicada siempre y cuando haya un \u00edndice apropiado en el espacio clave del lado derecho. As\u00ed que puedes hacer comparaciones de igualdad y comparaciones de no igualdad (b1.field = b2.field o b1.field\/=\/!=\/b2.field o b2.field is NOT NULL o expresi\u00f3n compleja = b2.field) Esto es un breve vistazo a la nueva caracter\u00edstica, para una inmersi\u00f3n m\u00e1s profunda en la caracter\u00edstica por favor revisa esta entrada de blog escrita por Bingjie Miao (el desarrollador que implement\u00f3 la caracter\u00edstica):<\/span><a href=\"https:\/\/www.couchbase.com\/blog\/es\/ansi-join-support-n1ql\/\"> <span style=\"font-weight: 400\">https:\/\/www.couchbase.com\/blog\/ansi-join-support-n1ql\/<\/span><\/a><\/p>\n<p><span style=\"font-weight: 400\">Ahora empezamos a entender que los JOINs ANSI tienen muy pocas limitaciones en comparaci\u00f3n con nuestros antiguos joins. El lado izquierdo de un ANSI join puede ser muy complejo, incluso puede ser varios joins en s\u00ed mismo, o una consulta anidada que resulta en algunos datos json, o varias consultas anidadas. Debido a este nivel de complejidad, es una mejor idea utilizar algo que llamamos RQG, en lugar de venir con consultas individuales para probar. He aqu\u00ed un breve resumen de c\u00f3mo funciona RQG.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Descripci\u00f3n general del generador de consultas aleatorias (RQG)<\/span><\/h3>\n<p><span style=\"font-weight: 400\">RQG es un framework escrito por Couchbase que aprovecha otro framework llamado <\/span><a href=\"https:\/\/launchpad.net\/randgen\"><span style=\"font-weight: 400\">Randgen<\/span><\/a><span style=\"font-weight: 400\">. B\u00e1sicamente especificamos un conjunto de par\u00e1metros en un archivo llamado gram\u00e1tica, y a partir de esos par\u00e1metros Randgen crear\u00e1 plantillas de consulta SQL (consultas con marcadores de posici\u00f3n para los nombres de campo y nombres de tabla), entonces nuestro marco procesa estas plantillas y las convierte en consultas con formato N1QL basadas en el conjunto de datos que se carga en couchbase.<\/span><\/p>\n<p><strong>Ejemplo de plantilla de consulta:<\/strong><\/p>\n<pre class=\"wrap:true lang:default decode:true\">SELECT NUMERIC_FIELD_LIST \r\nFROM BUCKET_NAME \r\nINNER JOIN BUCKET_NAME \r\nON ( PREVIOUS_TABLE.FIELD = CURRENT_TABLE.FIELD ) \r\nWHERE NOT (BOOL_FIELD != false);<\/pre>\n<p><span style=\"font-weight: 400\">Esta plantilla se genera a partir del archivo de gram\u00e1tica que contiene los par\u00e1metros, b\u00e1sicamente el archivo de gram\u00e1tica le dice a randgen que genere una consulta que seleccione una lista de datos de tipo num\u00e9rico de una uni\u00f3n de dos cubos arbitrarios en una comparaci\u00f3n de igualdad. La gram\u00e1tica tendr\u00e1 varios tipos de campos para seleccionar y varias condiciones de uni\u00f3n que se pueden introducir en los predicados ON\/ WHERE. Una vez generada la plantilla como se muestra arriba, nuestro marco de trabajo reemplazar\u00e1 estos valores arbitrarios con valores basados en los datos cargados. Para NUMERIC_FIELD_LIST seleccionar\u00e1 un campo que es una lista de ints\/bigints\/floats\/decimals\/etc dependiendo de lo que est\u00e9 disponible. El framework sustituir\u00e1 BUCKET_NAME por el nombre espec\u00edfico de un bucket que exista en el servidor. PREVIOUS_TABLE.FIELD ser\u00e1 un campo del primer bucket y CURRENT_TABLE.FIELD ser\u00e1 el mismo campo del segundo bucket. Una vez hecho esto, se repasar\u00e1 la consulta y se crear\u00e1 una copia de la misma en la que se eliminar\u00e1n las diferencias entre N1QL y SQL. Por ejemplo, en la antigua sintaxis join no pod\u00edamos usar la palabra clave ON, as\u00ed que en su lugar RQG convertir\u00eda ON a ON KEYS para las consultas n1ql. <\/span><\/p>\n<p><strong>Ejemplo de consulta convertida:<\/strong><\/p>\n<pre class=\"wrap:true lang:default decode:true\">SELECT t_3.decimal_field1 , t_3.int_field1 \r\nFROM multiple_table_db_87317649_simple_table_4 t_2 \r\nINNER JOIN multiple_table_db_87317649_simple_table_1 t_3 \r\nON KEYS [ t_2.primary_key_id ] \r\nWHERE (t_2.bool_field1 != false)<\/pre>\n<p><span style=\"font-weight: 400\">A continuaci\u00f3n, tanto las consultas n1ql como las consultas sql se ejecutan contra el servidor couchbase y un servidor MySQL equivalente. Los resultados de las consultas N1QL se comparan con los resultados de las consultas MySQL equivalentes. Nuestro objetivo es que nuestros resultados coincidan con los resultados de MySQL porque queremos que N1QL sea funcionalmente similar a SQL. Si quieres leer m\u00e1s acerca de c\u00f3mo est\u00e1 dise\u00f1ado RQG o c\u00f3mo genera plantillas y las convierte a n1ql por favor revisa esta serie de 5 partes sobre RQG:<\/span><a href=\"https:\/\/dzone.com\/articles\/testing-n1ql-sql-for-json\"> <span style=\"font-weight: 400\">https:\/\/dzone.com\/articles\/testing-n1ql-sql-for-json<\/span><\/a><\/p>\n<h3><span style=\"font-weight: 400\">USO DE RQG para comprobar los JOIN ANSI<\/span><\/h3>\n<p><span style=\"font-weight: 400\">La forma en que est\u00e1 configurado RQG nos permite generar una gran variedad de consultas que de otro modo no se nos habr\u00edan ocurrido a nosotros mismos. He aqu\u00ed una plantilla extremadamente complicada generada por RQG:<\/span><\/p>\n<pre class=\"right-set:true wrap:true lang:default decode:true\">SELECT NUMERIC_FIELD_LIST, STRING_FIELD_LIST \r\nFROM BUCKET_NAME \r\nINNER JOIN BUCKET_NAME \r\nON ( PREVIOUS_TABLE.FIELD = CURRENT_TABLE.FIELD ) \r\nWHERE (((((STRING_FIELD != STRING_VALUES AND (NUMERIC_FIELD BETWEEN LOWER_BOUND_VALUE and UPPER_BOUND_VALUE) OR (NUMERIC_FIELD BETWEEN LOWER_BOUND_VALUE and UPPER_BOUND_VALUE))) AND (NUMERIC_FIELD IS NOT NULL)) AND ((NOT (((BOOL_FIELD AND (NUMERIC_FIELD IS NULL) OR (NUMERIC_FIELD &gt;= NUMERIC_VALUE))) AND ((BOOL_FIELD != false AND NUMERIC_FIELD = NUMERIC_VALUE)) OR ((BOOL_FIELD != true AND NUMERIC_FIELD = NUMERIC_VALUE)) AND (NOT (BOOL_FIELD)))) AND (STRING_FIELD IS NULL))) AND (((BOOL_FIELD AND NUMERIC_FIELD != NUMERIC_VALUE)) AND ((BOOL_FIELD = true AND NUMERIC_FIELD IS NULL)))) OR (((NOT ((NUMERIC_FIELD &lt; NUMERIC_VALUE) AND ((BOOL_FIELD != false OR STRING_FIELD &lt; STRING_VALUES)))) AND (NOT (((STRING_FIELD IN ( LIST )) AND (STRING_FIELD LIKE STRING_VALUES) AND NUMERIC_FIELD IS NULL)))) OR (((BOOL_FIELD AND (NOT ((NUMERIC_FIELD = NUMERIC_VALUE) AND (NUMERIC_FIELD BETWEEN LOWER_BOUND_VALUE and UPPER_BOUND_VALUE))) OR (NUMERIC_FIELD &lt;= NUMERIC_VALUE))) OR (((NOT (((NOT ((BOOL_FIELD != true AND NUMERIC_FIELD &gt; NUMERIC_VALUE))) AND ((((BOOL_FIELD != false OR NUMERIC_FIELD != NUMERIC_VALUE)) AND ((BOOL_FIELD != true AND NUMERIC_FIELD BETWEEN LOWER_BOUND_VALUE and UPPER_BOUND_VALUE)) OR ((STRING_FIELD IS NOT NULL AND NUMERIC_FIELD &gt; NUMERIC_VALUE)) AND ((NUMERIC_FIELD &gt;= NUMERIC_VALUE AND STRING_FIELD = STRING_VALUES AND NOT (BOOL_FIELD)))) AND ((NOT (BOOL_FIELD) OR NUMERIC_FIELD IS NULL)))) AND (((NOT ((STRING_FIELD &gt;= STRING_VALUES AND NUMERIC_FIELD IS NULL))) OR (NOT ((((BOOL_FIELD AND NUMERIC_FIELD != NUMERIC_VALUE)) AND ((BOOL_FIELD != false OR NUMERIC_FIELD IS NULL))) AND (((STRING_FIELD IN ( LIST )) AND ((STRING_FIELD &lt;= STRING_VALUES AND NUMERIC_FIELD &lt;= NUMERIC_VALUE))) AND ((NUMERIC_FIELD BETWEEN LOWER_BOUND_VALUE and UPPER_BOUND_VALUE OR STRING_FIELD != STRING_VALUES)))))) OR ((STRING_FIELD &lt;= STRING_VALUES AND NUMERIC_FIELD &gt;= NUMERIC_VALUE))))) OR (NOT ((NOT ((BOOL_FIELD = false AND NUMERIC_FIELD IN ( LIST )))) OR (NOT ((BOOL_FIELD = true AND NUMERIC_FIELD &lt; NUMERIC_VALUE)))))) AND ((((BOOL_FIELD != true AND STRING_FIELD NOT BETWEEN LOWER_BOUND_VALUE and UPPER_BOUND_VALUE)) OR (((BOOL_FIELD = false OR (STRING_FIELD &lt; STRING_VALUES) OR ((STRING_FIELD &lt;= STRING_VALUES) OR (STRING_FIELD &gt;= STRING_VALUES)))) AND ((NOT (BOOL_FIELD) OR NUMERIC_FIELD IS NOT NULL)))) AND (((NOT (BOOL_FIELD) OR (STRING_FIELD &lt;= STRING_VALUES) OR (STRING_FIELD != STRING_VALUES))) OR ((NUMERIC_FIELD &lt; NUMERIC_VALUE OR STRING_FIELD IS NULL)))))));<\/pre>\n<p><span style=\"font-weight: 400\">Como puede ver por el tama\u00f1o de esta consulta, habr\u00eda sido muy dif\u00edcil crearla por nuestra cuenta, y muchas consultas de este tipo se generan y ejecutan a trav\u00e9s de RQG. Esta capacidad de crear consultas muy complejas lo hace perfectamente adecuado para abordar la complejidad arbitraria de los JOINs ANSI. La gram\u00e1tica que hemos definido para probar las uniones ANSI intenta capturar la complejidad del lado izquierdo de una uni\u00f3n, as\u00ed como la complejidad de la cl\u00e1usula ON. Le decimos a RQG que genere el <\/span><span style=\"font-weight: 400\">lado izquierdo<\/span><span style=\"font-weight: 400\">\u00a0de un join como una de estas tres cosas, un keyspace normal, una subconsulta n1ql o varios joins anidados. Le decimos a RQG que genere el <\/span><span style=\"font-weight: 400\">lado derecho<\/span><span style=\"font-weight: 400\"> de una uni\u00f3n como espacio de claves. A continuaci\u00f3n, le decimos a RQG que genere el <\/span><span style=\"font-weight: 400\">Cl\u00e1usula ON<\/span><span style=\"font-weight: 400\">\u00a0de un join como predicados mayoritariamente de igualdad entre dos campos uno del <\/span><span style=\"font-weight: 400\">espacio clave izquierdo o alias izquierdo<\/span><span style=\"font-weight: 400\">y <\/span><span style=\"font-weight: 400\">una del espacio de llaves de la derecha<\/span><span style=\"font-weight: 400\">. Las otras cosas que se pueden generar en la cl\u00e1usula ON podr\u00edan ser comparaciones de no igualdad (\/=\/!=) o simplemente comprobar atributos del campo keyspace de la derecha (b2.campo no es nulo, b2.campo no falta, b2.campo est\u00e1 en una lista, etc). Para ANSI JOINs, hay una peque\u00f1a diferencia entre n1ql y sql. Esa diferencia es que N1QL soporta la comparaci\u00f3n IS (NOT) MISSING, esto es debido al modelo de datos no relacional. Algunos buckets pueden tener documentos que tienen un campo que otros documentos en ese bucket no tienen. Entonces IS (NOT) MISSING significa que el campo no aparece en el documento(o en el caso de IS NOT MISSING significa que el campo aparece en el documento). T\u00e9cnicamente, si quisi\u00e9ramos tambi\u00e9n podr\u00edamos decirle a RQG que genere subconsultas n1ql dentro de la cl\u00e1usula ON y las compare con los valores del espacio clave de la derecha, sin embargo esto incrementar\u00eda exponencialmente el tiempo de ejecuci\u00f3n de nuestras consultas y no es un caso de uso com\u00fan. A continuaci\u00f3n se muestran algunos ejemplos de consultas ANSI JOIN generadas a partir de los par\u00e1metros anteriores:<\/span><\/p>\n<pre class=\"wrap:true lang:default decode:true\">SELECT OUTER_BUCKET_NAME.* \r\nFROM BUCKET_NAME \r\nINNER JOIN BUCKET_NAME \r\nON ( PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD ) \r\nWHERE NUMERIC_FIELD = NUMERIC_VALUE;<\/pre>\n<pre class=\"wrap:true lang:default decode:true\">SELECT OUTER_BUCKET_NAME.* \r\nFROM BUCKET_NAME \r\nINNER JOIN BUCKET_NAME \r\nON ( (PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD AND PREVIOUS_TABLE.NUMERIC_FIELD = CURRENT_TABLE.NUMERIC_FIELD) ) \r\nLEFT JOIN BUCKET_NAME \r\nON ( (PREVIOUS_TABLE.NUMERIC_FIELD = CURRENT_TABLE.NUMERIC_FIELD OR PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD) ) \r\nINNER JOIN BUCKET_NAME \r\nON ( NOT ((PREVIOUS_TABLE.NUMERIC_FIELD &lt; CURRENT_TABLE.NUMERIC_FIELD AND PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD)) ) \r\nINNER JOIN BUCKET_NAME \r\nON ( (PREVIOUS_TABLE.NUMERIC_FIELD = CURRENT_TABLE.NUMERIC_FIELD AND PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD AND PREVIOUS_TABLE.NUMERIC_FIELD = CURRENT_TABLE.NUMERIC_FIELD) ) \r\nINNER JOIN BUCKET_NAME \r\nON ( (PREVIOUS_TABLE.NUMERIC_FIELD = CURRENT_TABLE.NUMERIC_FIELD AND PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD) ) \r\nINNER JOIN BUCKET_NAME \r\nON ( (PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD AND PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD) ) \r\nINNER JOIN BUCKET_NAME \r\nON ( NOT ((PREVIOUS_TABLE.NUMERIC_FIELD != CURRENT_TABLE.NUMERIC_FIELD OR PREVIOUS_TABLE.STRING_FIELD = CURRENT_TABLE.STRING_FIELD)) ) \r\nINNER JOIN BUCKET_NAME \r\nON ( NOT ((PREVIOUS_TABLE.STRING_FIELD != CURRENT_TABLE.STRING_FIELD AND PREVIOUS_TABLE.NUMERIC_FIELD = CURRENT_TABLE.NUMERIC_FIELD)) ) \r\nWHERE NULL_NUM_FIELD IS NULL or NULL_NUM_FIELD IS MISSING;<\/pre>\n<p><span style=\"font-weight: 400\">Como se puede ver en estos ejemplos, la cl\u00e1usula ON puede ser varios predicados encadenados, encadenados por AND\/OR. Tambi\u00e9n podemos observar que se pueden ejecutar varias uniones en una consulta, y que cada uni\u00f3n puede tener su propia cl\u00e1usula ON. <\/span><\/p>\n<p><span style=\"font-weight: 400\">Ahora que se entiende c\u00f3mo RQG genera las plantillas y qu\u00e9 aspecto tienen esas plantillas, veamos un ejemplo de un error que encontramos en la funcionalidad ANSI JOIN que probablemente no habr\u00edamos encontrado de otra forma. <\/span><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-27483\"><span style=\"font-weight: 400\">MB-27483<\/span><\/a>, <span style=\"font-weight: 400\">en este fallo ten\u00edamos la siguiente consulta:<\/span><\/p>\n<pre class=\"right-set:true wrap:true lang:default decode:true\">SELECT t_2.* \r\nFROM multiple_table_db_492_simple_table_10 t_4 \r\nINNER JOIN multiple_table_db_492_simple_table_4 t_2 \r\nON ( NOT ((t_4.char_field1 = t_2.char_field1 AND t_4.int_field1 = t_2.int_field1)))\r\nWHERE (NOT ((t_2.bool_field1 = true AND t_2.decimal_field1 &lt; 4878))) OR ((((t_2.bool_field1 != true AND t_4.int_field1 IN [ 0 , 12 , 21 , 32 , 39 ])) OR ((t_2.decimal_field1 != 4878) OR (t_4.decimal_field1 &gt;= 4821))) AND (NOT (((NOT (t_4.bool_field1) OR t_2.char_field1 LIKE \"N\")) AND ((t_2.decimal_field1 BETWEEN 5 and 9985 AND t_2.varchar_field1 IS NULL AND t_2.bool_field1 = false))))) LIMIT 100<\/pre>\n<p><span style=\"font-weight: 400\">Esta consulta deber\u00eda haberse ejecutado con \u00e9xito dada la forma en que nuestro servidor estaba configurado, sin embargo, en lugar de ejecutarse estaba lanzando un error que el \u00edndice adecuado no exist\u00eda en el espacio clave de la derecha. El problema aqu\u00ed era que la cl\u00e1usula WHERE estaba interfiriendo con la selecci\u00f3n del \u00edndice de la cl\u00e1usula ON, causando que la consulta pensara que no ten\u00eda el \u00edndice que necesitaba cuando de hecho ese \u00edndice exist\u00eda. Si examinamos la cl\u00e1usula WHERE vemos que es muy compleja, no es el nivel de complejidad que normalmente tendr\u00edamos en la parte funcional de las pruebas. Por lo tanto, no habr\u00edamos detectado este error sin utilizar RQG. <\/span><\/p>\n<h3><span style=\"font-weight: 400\">Puntos clave <\/span><\/h3>\n<p><span style=\"font-weight: 400\">Los JOIN ANSI son bastante flexibles en cuanto a lo que es posible unir, se pueden unir expresiones arbitrarias con espacios clave y la cl\u00e1usula ON puede contener predicados que comparen expresiones arbitrarias con campos. Este nivel de complejidad hace que sea poco pr\u00e1ctico intentar crear consultas espec\u00edficas para probar cada escenario por nuestra cuenta mediante pruebas funcionales. Por suerte, disponemos de un marco de trabajo llamado RQG que es capaz de generar consultas basadas en un conjunto de reglas que podemos definir. Esta funcionalidad es muy potente y nos ha permitido probar ANSI JOINs a nuestra satisfacci\u00f3n. Por ejemplo, si se ejecuta un gran n\u00famero de consultas complejas, los resultados de ANSI JOIN se desviar\u00e1n en 1. Sin embargo, si se ejecuta una de esas consultas de forma aislada, los resultados ser\u00e1n correctos. Por eso confiamos en que los ANSI JOIN est\u00e9n en buena forma y listos para el uso de los clientes.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Lista de errores adicionales de ANSI JOIN encontrados con RQG:<\/span><\/h3>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400\">N\u00famero de error <\/span><\/td>\n<td><span style=\"font-weight: 400\">Descripci\u00f3n del fallo<\/span><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-27834\"><span style=\"font-weight: 400\">MB-27834<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">Esta consulta no utilizaba correctamente la sugerencia de consulta LIMIT, ejecutaba toda la consulta antes de aplicar el LIMIT <\/span><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-27763\"><span style=\"font-weight: 400\">MB-27763<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">Esta consulta no utilizaba correctamente la sugerencia de consulta LIMIT, similar al error anterior <\/span><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-27483\"><span style=\"font-weight: 400\">MB-27483<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">La consulta pensaba que el \u00edndice apropiado no exist\u00eda, lo que provocaba un error. Sin embargo, el \u00edndice estaba realmente presente en el sistema<\/span><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-27230\"><span style=\"font-weight: 400\">MB-27230<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">La consulta devolv\u00eda un error incorrecto <\/span><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-27201\"><span style=\"font-weight: 400\">MB-27201<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">Esta consulta se estaba ejecutando en un error con relleno no funciona correctamente<\/span><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-27109\"><span style=\"font-weight: 400\">MB-27109<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">Otra consulta que pensaba que el \u00edndice que necesitaba no estaba disponible, aunque el \u00edndice estaba presente en el sistema<\/span><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-27028\"><span style=\"font-weight: 400\">MB-27028<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">Cuando se ejecutaban varias consultas seguidas, algunos de los resultados se desviaban en 1. Cuando las consultas se ejecutaban solas, todos los resultados eran correctos.<\/span><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/issues.couchbase.com\/browse\/MB-26649\"><span style=\"font-weight: 400\">MB-26649<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">La consulta se colgaba intermitentemente<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><span style=\"font-weight: 400\">Anexo<\/span><\/h3>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Blog de Couchbase Server 5.5 GA <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/es\/announcing-couchbase-server-5-5\/\"><span style=\"font-weight: 400\">https:\/\/www.couchbase.com\/blog\/announcing-couchbase-server-5-5\/<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Uniones por \u00edndices <\/span><a href=\"https:\/\/dzone.com\/articles\/join-faster-with-couchbase-index-joins\"><span style=\"font-weight: 400\">https:\/\/dzone.com\/articles\/join-faster-with-couchbase-index-joins<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">ANSI JOINs Blog de Couchbase <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/es\/ansi-join-support-n1ql\/\"><span style=\"font-weight: 400\">https:\/\/www.couchbase.com\/blog\/ansi-join-support-n1ql\/<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Randgen <\/span><a href=\"https:\/\/launchpad.net\/randgen\"><span style=\"font-weight: 400\">https:\/\/launchpad.net\/randgen<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Serie de art\u00edculos RQG Dzone <\/span><a href=\"https:\/\/dzone.com\/articles\/testing-n1ql-sql-for-json\"><span style=\"font-weight: 400\">https:\/\/dzone.com\/articles\/testing-n1ql-sql-for-json<\/span><\/a><\/li>\n<\/ol>","protected":false},"excerpt":{"rendered":"<p>Overview The main purpose of this article is to show how Couchbase ANSI JOINs are tested. In Couchbase version 5.5, you can now execute joins using the ANSI standard syntax. This addition to joins makes them much more flexible, but [&hellip;]<\/p>","protected":false},"author":19919,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,1812],"tags":[2258,1877],"ppma_author":[9072],"class_list":["post-5609","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-n1ql-query","tag-5-5","tag-testing"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Testing ANSI JOINs - The Couchbase Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/testing-ansi-joins\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Testing ANSI JOINs\" \/>\n<meta property=\"og:description\" content=\"Overview The main purpose of this article is to show how Couchbase ANSI JOINs are tested. In Couchbase version 5.5, you can now execute joins using the ANSI standard syntax. This addition to joins makes them much more flexible, but [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/testing-ansi-joins\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-16T22:58:14+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-08-17T22:17:49+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Ajay Bhullar\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ajay Bhullar\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/\"},\"author\":{\"name\":\"Ajay Bhullar\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2c218cc6dcebf8b70696e10021b9d616\"},\"headline\":\"Testing ANSI JOINs\",\"datePublished\":\"2018-08-16T22:58:14+00:00\",\"dateModified\":\"2018-08-17T22:17:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/\"},\"wordCount\":1930,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"5.5\",\"testing\"],\"articleSection\":[\"Couchbase Server\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/\",\"name\":\"Testing ANSI JOINs - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2018-08-16T22:58:14+00:00\",\"dateModified\":\"2018-08-17T22:17:49+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Testing ANSI JOINs\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2c218cc6dcebf8b70696e10021b9d616\",\"name\":\"Ajay Bhullar\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/a30f56bcf3017b1a17f7950fb9d04fe9\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/3a8dfee793a89973baf873a87529774721a44593fdcb1162f81b133d63d0185c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/3a8dfee793a89973baf873a87529774721a44593fdcb1162f81b133d63d0185c?s=96&d=mm&r=g\",\"caption\":\"Ajay Bhullar\"},\"description\":\"Ajay Bhullar is a Software Engineer Tester in Couchbase from 2 years. Ajay is working on how Couchbase ANSI JOINs are tested and In Couchbase version 5.5, how you can execute joins using the ANSI standard syntax.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/ajaybhullar\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Testing ANSI JOINs - The Couchbase Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/testing-ansi-joins\/","og_locale":"es_MX","og_type":"article","og_title":"Testing ANSI JOINs","og_description":"Overview The main purpose of this article is to show how Couchbase ANSI JOINs are tested. In Couchbase version 5.5, you can now execute joins using the ANSI standard syntax. This addition to joins makes them much more flexible, but [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/es\/testing-ansi-joins\/","og_site_name":"The Couchbase Blog","article_published_time":"2018-08-16T22:58:14+00:00","article_modified_time":"2018-08-17T22:17:49+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Ajay Bhullar","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Ajay Bhullar","Est. reading time":"14 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/"},"author":{"name":"Ajay Bhullar","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2c218cc6dcebf8b70696e10021b9d616"},"headline":"Testing ANSI JOINs","datePublished":"2018-08-16T22:58:14+00:00","dateModified":"2018-08-17T22:17:49+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/"},"wordCount":1930,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["5.5","testing"],"articleSection":["Couchbase Server","SQL++ \/ N1QL Query"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/","url":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/","name":"Testing ANSI JOINs - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2018-08-16T22:58:14+00:00","dateModified":"2018-08-17T22:17:49+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/testing-ansi-joins\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Testing ANSI JOINs"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2c218cc6dcebf8b70696e10021b9d616","name":"Ajay Bhullar","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/a30f56bcf3017b1a17f7950fb9d04fe9","url":"https:\/\/secure.gravatar.com\/avatar\/3a8dfee793a89973baf873a87529774721a44593fdcb1162f81b133d63d0185c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3a8dfee793a89973baf873a87529774721a44593fdcb1162f81b133d63d0185c?s=96&d=mm&r=g","caption":"Ajay Bhullar"},"description":"Ajay Bhullar is a Software Engineer Tester in Couchbase from 2 years. Ajay is working on how Couchbase ANSI JOINs are tested and In Couchbase version 5.5, how you can execute joins using the ANSI standard syntax.","url":"https:\/\/www.couchbase.com\/blog\/es\/author\/ajaybhullar\/"}]}},"authors":[{"term_id":9072,"user_id":19919,"is_guest":0,"slug":"ajaybhullar","display_name":"Ajay Bhullar","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/3a8dfee793a89973baf873a87529774721a44593fdcb1162f81b133d63d0185c?s=96&d=mm&r=g","first_name":"Ajay","last_name":"Bhullar","user_url":"","author_category":"","description":"Ajay Bhullar es un Software Engineer Tester en Couchbase desde hace 2 a\u00f1os.\r\nAjay est\u00e1 trabajando en c\u00f3mo se prueban los JOINs ANSI de Couchbase y en la versi\u00f3n 5.5 de Couchbase, c\u00f3mo se pueden ejecutar joins usando la sintaxis est\u00e1ndar ANSI."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/5609","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/19919"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=5609"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/5609\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=5609"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=5609"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=5609"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=5609"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}